1 /*
2  * _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
3  */
4 
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8 
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "Ecore.h"
14 #include "ecore_x_private.h"
15 #include "Ecore_X.h"
16 
17 typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
18 
19 struct _Ecore_X_Startup_Info
20 {
21    Ecore_X_Window win;
22 
23    int            init;
24 
25    int            buffer_size;
26    char          *buffer;
27 
28    int            length;
29 
30    /* These are the sequence info fields */
31    char          *id;
32    char          *name;
33    int            screen;
34    char          *bin;
35    char          *icon;
36    int            desktop;
37    int            timestamp;
38    char          *description;
39    char          *wmclass;
40    int            silent;
41 };
42 
43 static void  _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
44                                                   Ecore_X_Atom atom,
45                                                   const char *str);
46 static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
47                                                   Ecore_X_Atom atom);
48 #if 0 /* Unused */
49 static int   _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
50 static int   _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
51                                                char *data);
52 #endif /* if 0 */
53 static void  _ecore_x_netwm_startup_info_free(void *data);
54 
55 /*
56  * Convenience macros
57  */
58 #define _ATOM_SET_UTF8_STRING_LIST(win, atom, string, cnt) \
59   XChangeProperty(_ecore_x_disp,                           \
60                   win,                                     \
61                   atom,                                    \
62                   ECORE_X_ATOM_UTF8_STRING,                \
63                   8,                                       \
64                   PropModeReplace,                         \
65                   (unsigned char *)string,                 \
66                   cnt)
67 
68 /*
69  * Local variables
70  */
71 
72 static Eina_Hash *startup_info = NULL;
73 
74 EAPI void
ecore_x_netwm_init(void)75 ecore_x_netwm_init(void)
76 {
77    LOGFN;
78    startup_info = eina_hash_string_superfast_new(
79        _ecore_x_netwm_startup_info_free);
80 }
81 
82 EAPI void
ecore_x_netwm_shutdown(void)83 ecore_x_netwm_shutdown(void)
84 {
85    LOGFN;
86    if (startup_info)
87      eina_hash_free(startup_info);
88 
89    startup_info = NULL;
90 }
91 
92 /*
93  * WM identification
94  */
95 EAPI void
ecore_x_netwm_wm_identify(Ecore_X_Window root,Ecore_X_Window check,const char * wm_name)96 ecore_x_netwm_wm_identify(Ecore_X_Window root,
97                           Ecore_X_Window check,
98                           const char *wm_name)
99 {
100    LOGFN;
101    ecore_x_window_prop_window_set(check,
102                                   ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
103                                   &check,
104                                   1);
105    _ecore_x_window_prop_string_utf8_set(check,
106                                         ECORE_X_ATOM_NET_WM_NAME,
107                                         wm_name);
108    /* This one isn't mandatory */
109    _ecore_x_window_prop_string_utf8_set(root,
110                                         ECORE_X_ATOM_NET_WM_NAME,
111                                         wm_name);
112    ecore_x_window_prop_window_set(root,
113                                   ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
114                                   &check,
115                                   1);
116 }
117 
118 /*
119  * Set supported atoms
120  */
121 EAPI void
ecore_x_netwm_supported_set(Ecore_X_Window root,Ecore_X_Atom * supported,int num)122 ecore_x_netwm_supported_set(Ecore_X_Window root,
123                             Ecore_X_Atom *supported,
124                             int num)
125 {
126    LOGFN;
127    ecore_x_window_prop_atom_set(root,
128                                 ECORE_X_ATOM_NET_SUPPORTED,
129                                 supported,
130                                 num);
131 }
132 
133 EAPI Eina_Bool
ecore_x_netwm_supported_get(Ecore_X_Window root,Ecore_X_Atom ** supported,int * num)134 ecore_x_netwm_supported_get(Ecore_X_Window root,
135                             Ecore_X_Atom **supported,
136                             int *num)
137 {
138    int num_ret;
139 
140    EINA_SAFETY_ON_NULL_RETURN_VAL(supported, EINA_FALSE);
141 
142    if (num)
143      *num = 0;
144 
145    LOGFN;
146    num_ret = ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED,
147                                                supported);
148    if (num_ret <= 0)
149      return EINA_FALSE;
150 
151    if (num)
152      *num = num_ret;
153 
154    return EINA_TRUE;
155 }
156 
157 /*
158  * Desktop configuration and status
159  */
160 EAPI void
ecore_x_netwm_desk_count_set(Ecore_X_Window root,unsigned int n_desks)161 ecore_x_netwm_desk_count_set(Ecore_X_Window root,
162                              unsigned int n_desks)
163 {
164    LOGFN;
165    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
166                                   &n_desks, 1);
167 }
168 
169 EAPI void
ecore_x_netwm_desk_roots_set(Ecore_X_Window root,Ecore_X_Window * vroots,unsigned int n_desks)170 ecore_x_netwm_desk_roots_set(Ecore_X_Window root,
171                              Ecore_X_Window *vroots,
172                              unsigned int n_desks)
173 {
174    LOGFN;
175    ecore_x_window_prop_window_set(root,
176                                   ECORE_X_ATOM_NET_VIRTUAL_ROOTS,
177                                   vroots,
178                                   n_desks);
179 }
180 
181 EAPI void
ecore_x_netwm_desk_names_set(Ecore_X_Window root,const char ** names,unsigned int n_desks)182 ecore_x_netwm_desk_names_set(Ecore_X_Window root,
183                              const char **names,
184                              unsigned int n_desks)
185 {
186    char ss[32], *buf, *t;
187    const char *s;
188    unsigned int i;
189    int l, len;
190 
191    LOGFN;
192    buf = NULL;
193    len = 0;
194 
195    for (i = 0; i < n_desks; i++)
196      {
197         s = (names) ? names[i] : NULL;
198         if (!s)
199           {
200              /* Default to "Desk-<number>" */
201              sprintf(ss, "Desk-%u", i);
202              s = ss;
203           }
204 
205         l = strlen(s) + 1;
206         t = realloc(buf, len + l);
207         if (t)
208           {
209              buf = t;
210              memcpy(buf + len, s, l);
211           }
212         len += l;
213      }
214 
215    _ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len);
216    if (_ecore_xlib_sync) ecore_x_sync();
217 
218    free(buf);
219 }
220 
221 EAPI void
ecore_x_netwm_desk_size_set(Ecore_X_Window root,unsigned int width,unsigned int height)222 ecore_x_netwm_desk_size_set(Ecore_X_Window root,
223                             unsigned int width,
224                             unsigned int height)
225 {
226    unsigned int size[2];
227 
228    LOGFN;
229    size[0] = width;
230    size[1] = height;
231    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size,
232                                   2);
233 }
234 
235 EAPI void
ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,unsigned int * origins,unsigned int n_desks)236 ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
237                                  unsigned int *origins,
238                                  unsigned int n_desks)
239 {
240    LOGFN;
241    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
242                                   origins, 2 * n_desks);
243 }
244 
245 EAPI void
ecore_x_netwm_desk_layout_set(Ecore_X_Window root,int orientation,int columns,int rows,int starting_corner)246 ecore_x_netwm_desk_layout_set(Ecore_X_Window root,
247                               int orientation,
248                               int columns,
249                               int rows,
250                               int starting_corner)
251 {
252    unsigned int layout[4];
253 
254    LOGFN;
255    layout[0] = orientation;
256    layout[1] = columns;
257    layout[2] = rows;
258    layout[3] = starting_corner;
259    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT,
260                                   layout, 4);
261 }
262 
263 EAPI void
ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,unsigned int * areas,unsigned int n_desks)264 ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
265                                  unsigned int *areas,
266                                  unsigned int n_desks)
267 {
268    LOGFN;
269    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas,
270                                   4 * n_desks);
271 }
272 
273 EAPI unsigned int *
ecore_x_netwm_desk_workareas_get(Ecore_X_Window root,unsigned int * n_desks)274 ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks)
275 {
276    int ret;
277    unsigned int *areas = NULL;
278 
279    if (!root) root = DefaultRootWindow(_ecore_x_disp);
280 
281    ret = ecore_x_window_prop_card32_list_get(root, ECORE_X_ATOM_NET_WORKAREA,
282                                              &areas);
283    if (!areas)
284      {
285         if (n_desks) *n_desks = 0;
286         return 0;
287      }
288    if (n_desks) *n_desks = ret / 4;
289    return areas;
290 }
291 
292 EAPI void
ecore_x_netwm_desk_current_set(Ecore_X_Window root,unsigned int desk)293 ecore_x_netwm_desk_current_set(Ecore_X_Window root,
294                                unsigned int desk)
295 {
296    LOGFN;
297    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk,
298                                   1);
299 }
300 
301 EAPI void
ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,Eina_Bool on)302 ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,
303                                   Eina_Bool on)
304 {
305    unsigned int val;
306 
307    LOGFN;
308    val = (on) ? 1 : 0;
309    ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val,
310                                   1);
311 }
312 
313 /*
314  * Client status
315  */
316 
317 /* Mapping order */
318 EAPI void
ecore_x_netwm_client_list_set(Ecore_X_Window root,Ecore_X_Window * p_clients,unsigned int n_clients)319 ecore_x_netwm_client_list_set(Ecore_X_Window root,
320                               Ecore_X_Window *p_clients,
321                               unsigned int n_clients)
322 {
323    LOGFN;
324    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST,
325                                   p_clients, n_clients);
326 }
327 
328 /* Stacking order */
329 EAPI void
ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,Ecore_X_Window * p_clients,unsigned int n_clients)330 ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,
331                                        Ecore_X_Window *p_clients,
332                                        unsigned int n_clients)
333 {
334    LOGFN;
335    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
336                                   p_clients, n_clients);
337 }
338 
339 EAPI void
ecore_x_netwm_client_active_set(Ecore_X_Window root,Ecore_X_Window win)340 ecore_x_netwm_client_active_set(Ecore_X_Window root,
341                                 Ecore_X_Window win)
342 {
343    LOGFN;
344    ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW,
345                                   &win, 1);
346 }
347 
348 EAPI void
ecore_x_netwm_client_active_request(Ecore_X_Window root,Ecore_X_Window win,int type,Ecore_X_Window current_win)349 ecore_x_netwm_client_active_request(Ecore_X_Window root,
350                                     Ecore_X_Window win,
351                                     int type,
352                                     Ecore_X_Window current_win)
353 {
354    XEvent xev = { 0 };
355 
356    LOGFN;
357    if (!root)
358      root = DefaultRootWindow(_ecore_x_disp);
359 
360    xev.xclient.type = ClientMessage;
361    xev.xclient.display = _ecore_x_disp;
362    xev.xclient.window = win;
363    xev.xclient.message_type = ECORE_X_ATOM_NET_ACTIVE_WINDOW;
364    xev.xclient.format = 32;
365    xev.xclient.data.l[0] = type;
366    xev.xclient.data.l[1] = CurrentTime;
367    xev.xclient.data.l[2] = current_win;
368    xev.xclient.data.l[3] = 0;
369    xev.xclient.data.l[4] = 0;
370 
371    XSendEvent(_ecore_x_disp, root, False,
372               SubstructureRedirectMask | SubstructureNotifyMask, &xev);
373    if (_ecore_xlib_sync) ecore_x_sync();
374 }
375 
376 EAPI void
ecore_x_netwm_name_set(Ecore_X_Window win,const char * name)377 ecore_x_netwm_name_set(Ecore_X_Window win,
378                        const char *name)
379 {
380    LOGFN;
381    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name);
382 }
383 
384 EAPI int
ecore_x_netwm_name_get(Ecore_X_Window win,char ** name)385 ecore_x_netwm_name_get(Ecore_X_Window win,
386                        char **name)
387 {
388    LOGFN;
389    if (name)
390      *name = _ecore_x_window_prop_string_utf8_get(win,
391                                                   ECORE_X_ATOM_NET_WM_NAME);
392 
393    return 1;
394 }
395 
396 EAPI void
ecore_x_netwm_startup_id_set(Ecore_X_Window win,const char * id)397 ecore_x_netwm_startup_id_set(Ecore_X_Window win,
398                              const char *id)
399 {
400    LOGFN;
401    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id);
402 }
403 
404 EAPI int
ecore_x_netwm_startup_id_get(Ecore_X_Window win,char ** id)405 ecore_x_netwm_startup_id_get(Ecore_X_Window win,
406                              char **id)
407 {
408    LOGFN;
409    if (id)
410      *id = _ecore_x_window_prop_string_utf8_get(win,
411                                                 ECORE_X_ATOM_NET_STARTUP_ID);
412 
413    return 1;
414 }
415 
416 EAPI void
ecore_x_netwm_visible_name_set(Ecore_X_Window win,const char * name)417 ecore_x_netwm_visible_name_set(Ecore_X_Window win,
418                                const char *name)
419 {
420    LOGFN;
421    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
422                                         name);
423 }
424 
425 EAPI int
ecore_x_netwm_visible_name_get(Ecore_X_Window win,char ** name)426 ecore_x_netwm_visible_name_get(Ecore_X_Window win,
427                                char **name)
428 {
429    LOGFN;
430    if (name)
431      *name = _ecore_x_window_prop_string_utf8_get(
432          win,
433          ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
434 
435    return 1;
436 }
437 
438 EAPI void
ecore_x_netwm_icon_name_set(Ecore_X_Window win,const char * name)439 ecore_x_netwm_icon_name_set(Ecore_X_Window win,
440                             const char *name)
441 {
442    LOGFN;
443    _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME,
444                                         name);
445 }
446 
447 EAPI int
ecore_x_netwm_icon_name_get(Ecore_X_Window win,char ** name)448 ecore_x_netwm_icon_name_get(Ecore_X_Window win,
449                             char **name)
450 {
451    LOGFN;
452    if (name)
453      *name = _ecore_x_window_prop_string_utf8_get(
454          win,
455          ECORE_X_ATOM_NET_WM_ICON_NAME);
456 
457    return 1;
458 }
459 
460 EAPI void
ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win,const char * name)461 ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win,
462                                     const char *name)
463 {
464    LOGFN;
465    _ecore_x_window_prop_string_utf8_set(win,
466                                         ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
467                                         name);
468 }
469 
470 EAPI int
ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win,char ** name)471 ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win,
472                                     char **name)
473 {
474    LOGFN;
475    if (name)
476      *name = _ecore_x_window_prop_string_utf8_get(
477          win,
478          ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
479 
480    return 1;
481 }
482 
483 EAPI void
ecore_x_netwm_desktop_set(Ecore_X_Window win,unsigned int desk)484 ecore_x_netwm_desktop_set(Ecore_X_Window win,
485                           unsigned int desk)
486 {
487    LOGFN;
488    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
489 }
490 
491 EAPI Eina_Bool
ecore_x_netwm_desktop_get(Ecore_X_Window win,unsigned int * desk)492 ecore_x_netwm_desktop_get(Ecore_X_Window win,
493                           unsigned int *desk)
494 {
495    int ret;
496    unsigned int tmp;
497 
498    LOGFN;
499    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP,
500                                         &tmp, 1);
501 
502    if (desk)
503      *desk = tmp;
504 
505    return ret == 1 ? EINA_TRUE : EINA_FALSE;
506 }
507 
508 /*
509  * _NET_WM_STRUT is deprecated
510  */
511 EAPI void
ecore_x_netwm_strut_set(Ecore_X_Window win,int left,int right,int top,int bottom)512 ecore_x_netwm_strut_set(Ecore_X_Window win,
513                         int left,
514                         int right,
515                         int top,
516                         int bottom)
517 {
518    unsigned int strut[4];
519 
520    LOGFN;
521    strut[0] = left;
522    strut[1] = right;
523    strut[2] = top;
524    strut[3] = bottom;
525    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
526 }
527 
528 /*
529  * _NET_WM_STRUT is deprecated
530  */
531 EAPI Eina_Bool
ecore_x_netwm_strut_get(Ecore_X_Window win,int * left,int * right,int * top,int * bottom)532 ecore_x_netwm_strut_get(Ecore_X_Window win,
533                         int *left,
534                         int *right,
535                         int *top,
536                         int *bottom)
537 {
538    int ret = 0;
539    unsigned int strut[4];
540 
541    LOGFN;
542    ret = ecore_x_window_prop_card32_get(win,
543                                         ECORE_X_ATOM_NET_WM_STRUT,
544                                         strut,
545                                         4);
546    if (ret != 4)
547      return EINA_FALSE;
548 
549    if (left)
550      *left = strut[0];
551 
552    if (right)
553      *right = strut[1];
554 
555    if (top)
556      *top = strut[2];
557 
558    if (bottom)
559      *bottom = strut[3];
560 
561    return EINA_TRUE;
562 }
563 
564 EAPI void
ecore_x_netwm_strut_partial_set(Ecore_X_Window win,int left,int right,int top,int bottom,int left_start_y,int left_end_y,int right_start_y,int right_end_y,int top_start_x,int top_end_x,int bottom_start_x,int bottom_end_x)565 ecore_x_netwm_strut_partial_set(Ecore_X_Window win,
566                                 int left,
567                                 int right,
568                                 int top,
569                                 int bottom,
570                                 int left_start_y,
571                                 int left_end_y,
572                                 int right_start_y,
573                                 int right_end_y,
574                                 int top_start_x,
575                                 int top_end_x,
576                                 int bottom_start_x,
577                                 int bottom_end_x)
578 {
579    unsigned int strut[12];
580 
581    LOGFN;
582    strut[0] = left;
583    strut[1] = right;
584    strut[2] = top;
585    strut[3] = bottom;
586    strut[4] = left_start_y;
587    strut[5] = left_end_y;
588    strut[6] = right_start_y;
589    strut[7] = right_end_y;
590    strut[8] = top_start_x;
591    strut[9] = top_end_x;
592    strut[10] = bottom_start_x;
593    strut[11] = bottom_end_x;
594    ecore_x_window_prop_card32_set(win,
595                                   ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
596                                   strut,
597                                   12);
598 }
599 
600 EAPI Eina_Bool
ecore_x_netwm_strut_partial_get(Ecore_X_Window win,int * left,int * right,int * top,int * bottom,int * left_start_y,int * left_end_y,int * right_start_y,int * right_end_y,int * top_start_x,int * top_end_x,int * bottom_start_x,int * bottom_end_x)601 ecore_x_netwm_strut_partial_get(Ecore_X_Window win,
602                                 int *left,
603                                 int *right,
604                                 int *top,
605                                 int *bottom,
606                                 int *left_start_y,
607                                 int *left_end_y,
608                                 int *right_start_y,
609                                 int *right_end_y,
610                                 int *top_start_x,
611                                 int *top_end_x,
612                                 int *bottom_start_x,
613                                 int *bottom_end_x)
614 {
615    int ret = 0;
616    unsigned int strut[12];
617 
618    LOGFN;
619    ret = ecore_x_window_prop_card32_get(win,
620                                         ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
621                                         strut,
622                                         12);
623    if (ret != 12)
624      return EINA_FALSE;
625 
626    if (left)
627      *left = strut[0];
628 
629    if (right)
630      *right = strut[1];
631 
632    if (top)
633      *top = strut[2];
634 
635    if (bottom)
636      *bottom = strut[3];
637 
638    if (left_start_y)
639      *left_start_y = strut[4];
640 
641    if (left_end_y)
642      *left_end_y = strut[5];
643 
644    if (right_start_y)
645      *right_start_y = strut[6];
646 
647    if (right_end_y)
648      *right_end_y = strut[7];
649 
650    if (top_start_x)
651      *top_start_x = strut[8];
652 
653    if (top_end_x)
654      *top_end_x = strut[9];
655 
656    if (bottom_start_x)
657      *bottom_start_x = strut[10];
658 
659    if (bottom_end_x)
660      *bottom_end_x = strut[11];
661 
662    return EINA_TRUE;
663 }
664 
665 EAPI void
ecore_x_netwm_icons_set(Ecore_X_Window win,Ecore_X_Icon * icon,int num)666 ecore_x_netwm_icons_set(Ecore_X_Window win,
667                         Ecore_X_Icon *icon,
668                         int num)
669 {
670    unsigned int *data, *p, *p2;
671    unsigned int i, size, x, y;
672 
673    LOGFN;
674    size = 0;
675    for (i = 0; i < (unsigned int)num; i++)
676      {
677         size += 2 + (icon[i].width * icon[i].height);
678      }
679    data = malloc(size * sizeof(unsigned int));
680    if (!data) return;
681    p = data;
682    for (i = 0; i < (unsigned int)num; i++)
683      {
684         p[0] = icon[i].width;
685         p[1] = icon[i].height;
686         p += 2;
687         p2 = icon[i].data;
688         for (y = 0; y < icon[i].height; y++)
689           {
690              for (x = 0; x < icon[i].width; x++)
691                {
692                   unsigned int r, g, b, a;
693 
694                   a = (*p2 >> 24) & 0xff;
695                   r = (*p2 >> 16) & 0xff;
696                   g = (*p2 >> 8 ) & 0xff;
697                   b = (*p2      ) & 0xff;
698                   if ((a > 0) && (a < 255))
699                     {
700                        // unpremul
701                        r = (r * 255) / a;
702                        g = (g * 255) / a;
703                        b = (b * 255) / a;
704                     }
705                   *p = (a << 24) | (r << 16) | (g << 8) | b;
706                   p++;
707                   p2++;
708                }
709           }
710      }
711    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON,
712                                   data, size);
713    free(data);
714 }
715 
716 EAPI Eina_Bool
ecore_x_netwm_icons_get(Ecore_X_Window win,Ecore_X_Icon ** icon,int * num)717 ecore_x_netwm_icons_get(Ecore_X_Window win,
718                         Ecore_X_Icon **icon,
719                         int *num)
720 {
721    unsigned int *data, *p;
722    unsigned int *src;
723    unsigned int len, icons, i;
724    int num_ret;
725 
726    LOGFN;
727    if (num)
728      *num = 0;
729 
730    if (icon)
731      *icon = NULL;
732 
733    num_ret = ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON,
734                                                  &data);
735    if (num_ret <= 0)
736      return EINA_FALSE;
737 
738    if (!data)
739      return EINA_FALSE;
740 
741    if (num_ret < 2)
742      {
743         free(data);
744         return EINA_FALSE;
745      }
746 
747    /* Check how many icons there are */
748    icons = 0;
749    p = data;
750    while (p)
751      {
752         len = p[0] * p[1];
753         p += (len + 2);
754         if ((p - data) > num_ret)
755           {
756              free(data);
757              return EINA_FALSE;
758           }
759 
760         icons++;
761 
762         if ((p - data) == num_ret)
763           p = NULL;
764      }
765    if (num)
766      *num = icons;
767 
768    /* If the user doesn't want the icons, return */
769    if (!icon)
770      {
771         free(data);
772         return EINA_TRUE;
773      }
774 
775    /* Allocate memory */
776    *icon = malloc(icons * sizeof(Ecore_X_Icon));
777    if (!(*icon))
778      {
779         free(data);
780         return EINA_FALSE;
781      }
782 
783    /* Fetch the icons */
784    p = data;
785    for (i = 0; i < icons; i++)
786      {
787         unsigned int *ps, *pd, *pe;
788 
789         len = p[0] * p[1];
790         ((*icon)[i]).width = p[0];
791         ((*icon)[i]).height = p[1];
792         src = &(p[2]);
793         ((*icon)[i]).data = malloc(len * sizeof(unsigned int));
794         if (!((*icon)[i]).data)
795           {
796              while (i)
797                free(((*icon)[--i]).data);
798              free(*icon);
799              free(data);
800              return EINA_FALSE;
801           }
802 
803         pd = ((*icon)[i]).data;
804         ps = src;
805         pe = ps + len;
806         for (; ps < pe; ps++)
807           {
808              unsigned int r, g, b, a;
809 
810              a = (*ps >> 24) & 0xff;
811              r = (((*ps >> 16) & 0xff) * a) / 255;
812              g = (((*ps >> 8) & 0xff) * a) / 255;
813              b = (((*ps) & 0xff) * a) / 255;
814              *pd = (a << 24) | (r << 16) | (g << 8) | (b);
815              pd++;
816           }
817         p += (len + 2);
818      }
819 
820    free(data);
821 
822    return EINA_TRUE;
823 }
824 
825 EAPI void
ecore_x_netwm_icon_geometry_set(Ecore_X_Window win,int x,int y,int width,int height)826 ecore_x_netwm_icon_geometry_set(Ecore_X_Window win,
827                                 int x,
828                                 int y,
829                                 int width,
830                                 int height)
831 {
832    unsigned int geometry[4];
833 
834    LOGFN;
835    geometry[0] = x;
836    geometry[1] = y;
837    geometry[2] = width;
838    geometry[3] = height;
839    ecore_x_window_prop_card32_set(win,
840                                   ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
841                                   geometry,
842                                   4);
843 }
844 
845 EAPI Eina_Bool
ecore_x_netwm_icon_geometry_get(Ecore_X_Window win,int * x,int * y,int * width,int * height)846 ecore_x_netwm_icon_geometry_get(Ecore_X_Window win,
847                                 int *x,
848                                 int *y,
849                                 int *width,
850                                 int *height)
851 {
852    int ret;
853    unsigned int geometry[4];
854 
855    LOGFN;
856    ret = ecore_x_window_prop_card32_get(win,
857                                         ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
858                                         geometry,
859                                         4);
860    if (ret != 4)
861      return EINA_FALSE;
862 
863    if (x)
864      *x = geometry[0];
865 
866    if (y)
867      *y = geometry[1];
868 
869    if (width)
870      *width = geometry[2];
871 
872    if (height)
873      *height = geometry[3];
874 
875    return EINA_TRUE;
876 }
877 
878 EAPI void
ecore_x_netwm_pid_set(Ecore_X_Window win,int pid)879 ecore_x_netwm_pid_set(Ecore_X_Window win,
880                       int pid)
881 {
882    unsigned int tmp;
883 
884    LOGFN;
885    tmp = pid;
886    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID,
887                                   &tmp, 1);
888 }
889 
890 EAPI Eina_Bool
ecore_x_netwm_pid_get(Ecore_X_Window win,int * pid)891 ecore_x_netwm_pid_get(Ecore_X_Window win,
892                       int *pid)
893 {
894    int ret;
895    unsigned int tmp;
896 
897    LOGFN;
898    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID,
899                                         &tmp, 1);
900    if (pid)
901      *pid = tmp;
902 
903    return ret == 1 ? EINA_TRUE : EINA_FALSE;
904 }
905 
906 EAPI void
ecore_x_netwm_handled_icons_set(Ecore_X_Window win)907 ecore_x_netwm_handled_icons_set(Ecore_X_Window win)
908 {
909    LOGFN;
910    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
911                                   NULL, 0);
912 }
913 
914 EAPI Eina_Bool
ecore_x_netwm_handled_icons_get(Ecore_X_Window win)915 ecore_x_netwm_handled_icons_get(Ecore_X_Window win)
916 {
917    int ret = 0;
918    LOGFN;
919    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
920                                         NULL, 0);
921    return ret == 0 ? EINA_TRUE : EINA_FALSE;
922 }
923 
924 EAPI void
ecore_x_netwm_user_time_set(Ecore_X_Window win,unsigned int tim)925 ecore_x_netwm_user_time_set(Ecore_X_Window win,
926                             unsigned int tim)
927 {
928    LOGFN;
929    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME,
930                                   &tim, 1);
931 }
932 
933 EAPI Eina_Bool
ecore_x_netwm_user_time_get(Ecore_X_Window win,unsigned int * tim)934 ecore_x_netwm_user_time_get(Ecore_X_Window win,
935                             unsigned int *tim)
936 {
937    int ret;
938    unsigned int tmp;
939 
940    LOGFN;
941    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME,
942                                         &tmp, 1);
943    if (tim)
944      *tim = tmp;
945 
946    return ret == 1 ? EINA_TRUE : EINA_FALSE;
947 }
948 
949 Ecore_X_Window_State
_ecore_x_netwm_state_get(Ecore_X_Atom a)950 _ecore_x_netwm_state_get(Ecore_X_Atom a)
951 {
952    if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
953      return ECORE_X_WINDOW_STATE_MODAL;
954    else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
955      return ECORE_X_WINDOW_STATE_STICKY;
956    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
957      return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
958    else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
959      return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
960    else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
961      return ECORE_X_WINDOW_STATE_SHADED;
962    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
963      return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
964    else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
965      return ECORE_X_WINDOW_STATE_SKIP_PAGER;
966    else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
967      return ECORE_X_WINDOW_STATE_HIDDEN;
968    else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
969      return ECORE_X_WINDOW_STATE_FULLSCREEN;
970    else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
971      return ECORE_X_WINDOW_STATE_ABOVE;
972    else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
973      return ECORE_X_WINDOW_STATE_BELOW;
974    else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
975      return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
976    else
977      return ECORE_X_WINDOW_STATE_UNKNOWN;
978 }
979 
980 static Ecore_X_Atom
_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)981 _ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
982 {
983    switch (s)
984      {
985       case ECORE_X_WINDOW_STATE_MODAL:
986         return ECORE_X_ATOM_NET_WM_STATE_MODAL;
987 
988       case ECORE_X_WINDOW_STATE_STICKY:
989         return ECORE_X_ATOM_NET_WM_STATE_STICKY;
990 
991       case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
992         return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
993 
994       case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
995         return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
996 
997       case ECORE_X_WINDOW_STATE_SHADED:
998         return ECORE_X_ATOM_NET_WM_STATE_SHADED;
999 
1000       case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
1001         return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
1002 
1003       case ECORE_X_WINDOW_STATE_SKIP_PAGER:
1004         return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
1005 
1006       case ECORE_X_WINDOW_STATE_HIDDEN:
1007         return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
1008 
1009       case ECORE_X_WINDOW_STATE_FULLSCREEN:
1010         return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
1011 
1012       case ECORE_X_WINDOW_STATE_ABOVE:
1013         return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
1014 
1015       case ECORE_X_WINDOW_STATE_BELOW:
1016         return ECORE_X_ATOM_NET_WM_STATE_BELOW;
1017 
1018       case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
1019         return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
1020 
1021       default:
1022         return 0;
1023      }
1024 }
1025 
1026 EAPI void
ecore_x_netwm_window_state_set(Ecore_X_Window win,Ecore_X_Window_State * state,unsigned int num)1027 ecore_x_netwm_window_state_set(Ecore_X_Window win,
1028                                Ecore_X_Window_State *state,
1029                                unsigned int num)
1030 {
1031    Ecore_X_Atom *set;
1032    unsigned int i;
1033 
1034    LOGFN;
1035    if (!num)
1036      {
1037         ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE);
1038         return;
1039      }
1040 
1041    set = malloc(num * sizeof(Ecore_X_Atom));
1042    if (!set)
1043      return;
1044 
1045    for (i = 0; i < num; i++)
1046      set[i] = _ecore_x_netwm_state_atom_get(state[i]);
1047 
1048    ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num);
1049 
1050    free(set);
1051 }
1052 
1053 EAPI Eina_Bool
ecore_x_netwm_window_state_get(Ecore_X_Window win,Ecore_X_Window_State ** state,unsigned int * num)1054 ecore_x_netwm_window_state_get(Ecore_X_Window win,
1055                                Ecore_X_Window_State **state,
1056                                unsigned int *num)
1057 {
1058    int num_ret, i;
1059    Ecore_X_Atom *atoms;
1060 
1061    LOGFN;
1062    if (num)
1063      *num = 0;
1064 
1065    if (state)
1066      *state = NULL;
1067 
1068    num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE,
1069                                                &atoms);
1070    if (num_ret <= 0)
1071      return EINA_FALSE;
1072 
1073    if (state)
1074      {
1075         *state = malloc(num_ret * sizeof(Ecore_X_Window_State));
1076         if (*state)
1077           for (i = 0; i < num_ret; ++i)
1078             (*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
1079 
1080         if (num)
1081           *num = num_ret;
1082      }
1083 
1084    free(atoms);
1085    return EINA_TRUE;
1086 }
1087 
1088 static Ecore_X_Window_Type
_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)1089 _ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
1090 {
1091    if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
1092      return ECORE_X_WINDOW_TYPE_DESKTOP;
1093    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
1094      return ECORE_X_WINDOW_TYPE_DOCK;
1095    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
1096      return ECORE_X_WINDOW_TYPE_TOOLBAR;
1097    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
1098      return ECORE_X_WINDOW_TYPE_MENU;
1099    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
1100      return ECORE_X_WINDOW_TYPE_UTILITY;
1101    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
1102      return ECORE_X_WINDOW_TYPE_SPLASH;
1103    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
1104      return ECORE_X_WINDOW_TYPE_DIALOG;
1105    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
1106      return ECORE_X_WINDOW_TYPE_NORMAL;
1107    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
1108      return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU;
1109    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU)
1110      return ECORE_X_WINDOW_TYPE_POPUP_MENU;
1111    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP)
1112      return ECORE_X_WINDOW_TYPE_TOOLTIP;
1113    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION)
1114      return ECORE_X_WINDOW_TYPE_NOTIFICATION;
1115    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO)
1116      return ECORE_X_WINDOW_TYPE_COMBO;
1117    else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND)
1118      return ECORE_X_WINDOW_TYPE_DND;
1119    else
1120      return ECORE_X_WINDOW_TYPE_UNKNOWN;
1121 }
1122 
1123 static Ecore_X_Atom
_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)1124 _ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
1125 {
1126    switch (type)
1127      {
1128       case ECORE_X_WINDOW_TYPE_DESKTOP:
1129         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
1130 
1131       case ECORE_X_WINDOW_TYPE_DOCK:
1132         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
1133 
1134       case ECORE_X_WINDOW_TYPE_TOOLBAR:
1135         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
1136 
1137       case ECORE_X_WINDOW_TYPE_MENU:
1138         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
1139 
1140       case ECORE_X_WINDOW_TYPE_UTILITY:
1141         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
1142 
1143       case ECORE_X_WINDOW_TYPE_SPLASH:
1144         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
1145 
1146       case ECORE_X_WINDOW_TYPE_DIALOG:
1147         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
1148 
1149       case ECORE_X_WINDOW_TYPE_NORMAL:
1150         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
1151 
1152       case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU:
1153         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
1154 
1155       case ECORE_X_WINDOW_TYPE_POPUP_MENU:
1156         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU;
1157 
1158       case ECORE_X_WINDOW_TYPE_TOOLTIP:
1159         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP;
1160 
1161       case ECORE_X_WINDOW_TYPE_NOTIFICATION:
1162         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION;
1163 
1164       case ECORE_X_WINDOW_TYPE_COMBO:
1165         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO;
1166 
1167       case ECORE_X_WINDOW_TYPE_DND:
1168         return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND;
1169 
1170       default:
1171         return 0;
1172      }
1173 }
1174 
1175 /*
1176  * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
1177  * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
1178  */
1179 EAPI void
ecore_x_netwm_window_type_set(Ecore_X_Window win,Ecore_X_Window_Type type)1180 ecore_x_netwm_window_type_set(Ecore_X_Window win,
1181                               Ecore_X_Window_Type type)
1182 {
1183    Ecore_X_Atom atom;
1184 
1185    LOGFN;
1186    atom = _ecore_x_netwm_window_type_atom_get(type);
1187    ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1188                                 &atom, 1);
1189 }
1190 
1191 /* FIXME: Maybe return 0 on some conditions? */
1192 EAPI Eina_Bool
ecore_x_netwm_window_type_get(Ecore_X_Window win,Ecore_X_Window_Type * type)1193 ecore_x_netwm_window_type_get(Ecore_X_Window win,
1194                               Ecore_X_Window_Type *type)
1195 {
1196    int num;
1197    Ecore_X_Atom *atoms = NULL;
1198 
1199    LOGFN;
1200    if (type)
1201      *type = ECORE_X_WINDOW_TYPE_NORMAL;
1202 
1203    num = ecore_x_window_prop_atom_list_get(win,
1204                                            ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1205                                            &atoms);
1206    if ((type) && (num >= 1) && (atoms))
1207      *type = _ecore_x_netwm_window_type_type_get(atoms[0]);
1208 
1209    free(atoms);
1210    if (num >= 1)
1211      return EINA_TRUE;
1212 
1213    return EINA_FALSE;
1214 }
1215 
1216 EAPI int
ecore_x_netwm_window_types_get(Ecore_X_Window win,Ecore_X_Window_Type ** types)1217 ecore_x_netwm_window_types_get(Ecore_X_Window win,
1218                                Ecore_X_Window_Type **types)
1219 {
1220    int num, i;
1221    Ecore_X_Atom *atoms = NULL;
1222    Ecore_X_Window_Type *atoms2 = NULL;
1223 
1224    LOGFN;
1225    if (types)
1226      *types = NULL;
1227 
1228    num = ecore_x_window_prop_atom_list_get(win,
1229                                            ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1230                                            &atoms);
1231    if ((num <= 0) || (!atoms))
1232      {
1233         if (atoms)
1234           free(atoms);
1235 
1236         return 0;
1237      }
1238 
1239    atoms2 = malloc(num * sizeof(Ecore_X_Window_Type));
1240    if (!atoms2)
1241      {
1242         if (atoms) free(atoms);
1243         return 0;
1244      }
1245 
1246    for (i = 0; i < num; i++)
1247      atoms2[i] = _ecore_x_netwm_window_type_type_get(atoms[i]);
1248    free(atoms);
1249    if (types)
1250      *types = atoms2;
1251    else
1252      free(atoms2);
1253 
1254    return num;
1255 }
1256 
1257 static Ecore_X_Atom
_ecore_x_netwm_action_atom_get(Ecore_X_Action action)1258 _ecore_x_netwm_action_atom_get(Ecore_X_Action action)
1259 {
1260    switch (action)
1261      {
1262       case ECORE_X_ACTION_MOVE:
1263         return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
1264 
1265       case ECORE_X_ACTION_RESIZE:
1266         return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
1267 
1268       case ECORE_X_ACTION_MINIMIZE:
1269         return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
1270 
1271       case ECORE_X_ACTION_SHADE:
1272         return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
1273 
1274       case ECORE_X_ACTION_STICK:
1275         return ECORE_X_ATOM_NET_WM_ACTION_STICK;
1276 
1277       case ECORE_X_ACTION_MAXIMIZE_HORZ:
1278         return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
1279 
1280       case ECORE_X_ACTION_MAXIMIZE_VERT:
1281         return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
1282 
1283       case ECORE_X_ACTION_FULLSCREEN:
1284         return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
1285 
1286       case ECORE_X_ACTION_CHANGE_DESKTOP:
1287         return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
1288 
1289       case ECORE_X_ACTION_CLOSE:
1290         return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
1291 
1292       case ECORE_X_ACTION_ABOVE:
1293         return ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
1294 
1295       case ECORE_X_ACTION_BELOW:
1296         return ECORE_X_ATOM_NET_WM_ACTION_BELOW;
1297 
1298       default:
1299         return 0;
1300      }
1301 }
1302 
1303 /* FIXME: Get complete list */
1304 EAPI Eina_Bool
ecore_x_netwm_allowed_action_isset(Ecore_X_Window win,Ecore_X_Action action)1305 ecore_x_netwm_allowed_action_isset(Ecore_X_Window win,
1306                                    Ecore_X_Action action)
1307 {
1308    int num, i;
1309    Ecore_X_Atom *atoms, atom;
1310    Eina_Bool ret = EINA_FALSE;
1311 
1312    LOGFN;
1313    num = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
1314                                            &atoms);
1315    if (num <= 0)
1316      return ret;
1317 
1318    atom = _ecore_x_netwm_action_atom_get(action);
1319 
1320    for (i = 0; i < num; ++i)
1321      {
1322         if (atom == atoms[i])
1323           {
1324              ret = 1;
1325              break;
1326           }
1327      }
1328 
1329    free(atoms);
1330    return ret;
1331 }
1332 
1333 /* FIXME: Set complete list */
1334 EAPI void
ecore_x_netwm_allowed_action_set(Ecore_X_Window win,Ecore_X_Action * action,unsigned int num)1335 ecore_x_netwm_allowed_action_set(Ecore_X_Window win,
1336                                  Ecore_X_Action *action,
1337                                  unsigned int num)
1338 {
1339    Ecore_X_Atom *set;
1340    unsigned int i;
1341 
1342    LOGFN;
1343    if (!num)
1344      {
1345         ecore_x_window_prop_property_del(win,
1346                                          ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
1347         return;
1348      }
1349 
1350    set = malloc(num * sizeof(Ecore_X_Atom));
1351    if (!set)
1352      return;
1353 
1354    for (i = 0; i < num; i++)
1355      set[i] = _ecore_x_netwm_action_atom_get(action[i]);
1356 
1357    ecore_x_window_prop_atom_set(win,
1358                                 ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
1359                                 set,
1360                                 num);
1361 
1362    free(set);
1363 }
1364 
1365 EAPI Eina_Bool
ecore_x_netwm_allowed_action_get(Ecore_X_Window win,Ecore_X_Action ** action,unsigned int * num)1366 ecore_x_netwm_allowed_action_get(Ecore_X_Window win,
1367                                  Ecore_X_Action **action,
1368                                  unsigned int *num)
1369 {
1370    int num_ret, i;
1371    Ecore_X_Atom *atoms;
1372 
1373    LOGFN;
1374    if (num)
1375      *num = 0;
1376 
1377    if (action)
1378      *action = NULL;
1379 
1380    num_ret = ecore_x_window_prop_atom_list_get(
1381        win,
1382        ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
1383        &atoms);
1384    if (num_ret <= 0)
1385      return EINA_FALSE;
1386 
1387    if (action)
1388      {
1389         *action = malloc(num_ret * sizeof(Ecore_X_Action));
1390         if (*action)
1391           for (i = 0; i < num_ret; ++i)
1392             (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
1393 
1394         if (num)
1395           *num = num_ret;
1396      }
1397 
1398    free(atoms);
1399    return EINA_TRUE;
1400 }
1401 
1402 EAPI void
ecore_x_netwm_opacity_set(Ecore_X_Window win,unsigned int opacity)1403 ecore_x_netwm_opacity_set(Ecore_X_Window win,
1404                           unsigned int opacity)
1405 {
1406    LOGFN;
1407    ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1408                                   &opacity, 1);
1409 }
1410 
1411 EAPI Eina_Bool
ecore_x_netwm_opacity_get(Ecore_X_Window win,unsigned int * opacity)1412 ecore_x_netwm_opacity_get(Ecore_X_Window win,
1413                           unsigned int *opacity)
1414 {
1415    int ret;
1416    unsigned int tmp;
1417 
1418    LOGFN;
1419    ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
1420                                         &tmp, 1);
1421    if (opacity)
1422      *opacity = tmp;
1423 
1424    return ret == 1 ? EINA_TRUE : EINA_FALSE;
1425 }
1426 
1427 EAPI void
ecore_x_netwm_frame_size_set(Ecore_X_Window win,int fl,int fr,int ft,int fb)1428 ecore_x_netwm_frame_size_set(Ecore_X_Window win,
1429                              int fl,
1430                              int fr,
1431                              int ft,
1432                              int fb)
1433 {
1434    unsigned int frames[4];
1435 
1436    LOGFN;
1437    frames[0] = fl;
1438    frames[1] = fr;
1439    frames[2] = ft;
1440    frames[3] = fb;
1441    ecore_x_window_prop_card32_set(win,
1442                                   ECORE_X_ATOM_NET_FRAME_EXTENTS,
1443                                   frames,
1444                                   4);
1445 }
1446 
1447 EAPI Eina_Bool
ecore_x_netwm_frame_size_get(Ecore_X_Window win,int * fl,int * fr,int * ft,int * fb)1448 ecore_x_netwm_frame_size_get(Ecore_X_Window win,
1449                              int *fl,
1450                              int *fr,
1451                              int *ft,
1452                              int *fb)
1453 {
1454    int ret = 0;
1455    unsigned int frames[4];
1456 
1457    LOGFN;
1458    ret = ecore_x_window_prop_card32_get(win,
1459                                         ECORE_X_ATOM_NET_FRAME_EXTENTS,
1460                                         frames,
1461                                         4);
1462    if (ret != 4)
1463      return EINA_FALSE;
1464 
1465    if (fl)
1466      *fl = frames[0];
1467 
1468    if (fr)
1469      *fr = frames[1];
1470 
1471    if (ft)
1472      *ft = frames[2];
1473 
1474    if (fb)
1475      *fb = frames[3];
1476 
1477    return EINA_TRUE;
1478 }
1479 
1480 EAPI Eina_Bool
ecore_x_netwm_sync_counter_get(Ecore_X_Window win,Ecore_X_Sync_Counter * counter)1481 ecore_x_netwm_sync_counter_get(Ecore_X_Window win,
1482                                Ecore_X_Sync_Counter *counter)
1483 {
1484    int ret;
1485    unsigned int tmp;
1486 
1487    LOGFN;
1488    ret = ecore_x_window_prop_card32_get(
1489        win,
1490        ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
1491        &tmp,
1492        1);
1493 
1494    if (counter)
1495      *counter = tmp;
1496 
1497    return ret == 1 ? EINA_TRUE : EINA_FALSE;
1498 }
1499 
1500 EAPI void
ecore_x_netwm_ping_send(Ecore_X_Window win)1501 ecore_x_netwm_ping_send(Ecore_X_Window win)
1502 {
1503    XEvent xev = { 0 };
1504 
1505    if (!win)
1506      return;
1507 
1508    LOGFN;
1509    xev.xclient.type = ClientMessage;
1510    xev.xclient.display = _ecore_x_disp;
1511    xev.xclient.window = win;
1512    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
1513    xev.xclient.format = 32;
1514    xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_PING;
1515    xev.xclient.data.l[1] = _ecore_x_event_last_time;
1516    xev.xclient.data.l[2] = win;
1517    xev.xclient.data.l[3] = 0;
1518    xev.xclient.data.l[4] = 0;
1519 
1520    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
1521    if (_ecore_xlib_sync) ecore_x_sync();
1522 }
1523 
1524 EAPI void
ecore_x_netwm_sync_request_send(Ecore_X_Window win,unsigned int serial)1525 ecore_x_netwm_sync_request_send(Ecore_X_Window win,
1526                                 unsigned int serial)
1527 {
1528    XSyncValue value;
1529    XEvent xev = { 0 };
1530 
1531    if (!win)
1532      return;
1533 
1534    LOGFN;
1535    XSyncIntToValue(&value, (int)serial);
1536 
1537    xev.xclient.type = ClientMessage;
1538    xev.xclient.display = _ecore_x_disp;
1539    xev.xclient.window = win;
1540    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
1541    xev.xclient.format = 32;
1542    xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
1543    xev.xclient.data.l[1] = _ecore_x_event_last_time;
1544    xev.xclient.data.l[2] = XSyncValueLow32(value);
1545    xev.xclient.data.l[3] = XSyncValueHigh32(value);
1546    xev.xclient.data.l[4] = 0;
1547 
1548    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
1549    if (_ecore_xlib_sync) ecore_x_sync();
1550 }
1551 
1552 EAPI void
ecore_x_netwm_state_request_send(Ecore_X_Window win,Ecore_X_Window root,Ecore_X_Window_State s1,Ecore_X_Window_State s2,Eina_Bool set)1553 ecore_x_netwm_state_request_send(Ecore_X_Window win,
1554                                  Ecore_X_Window root,
1555                                  Ecore_X_Window_State s1,
1556                                  Ecore_X_Window_State s2,
1557                                  Eina_Bool set)
1558 {
1559    XEvent xev = { 0 };
1560 
1561    if (!win)
1562      return;
1563 
1564    LOGFN;
1565    if (!root)
1566      root = DefaultRootWindow(_ecore_x_disp);
1567 
1568    xev.xclient.type = ClientMessage;
1569    xev.xclient.serial = 0;
1570    xev.xclient.send_event = True;
1571    xev.xclient.display = _ecore_x_disp;
1572    xev.xclient.window = win;
1573    xev.xclient.format = 32;
1574    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_STATE;
1575    xev.xclient.data.l[0] = !!set;
1576    xev.xclient.data.l[1] = _ecore_x_netwm_state_atom_get(s1);
1577    xev.xclient.data.l[2] = _ecore_x_netwm_state_atom_get(s2);
1578    /* 1 == normal client, if someone wants to use this
1579     * function in a pager, this should be 2 */
1580    xev.xclient.data.l[3] = 1;
1581    xev.xclient.data.l[4] = 0;
1582 
1583    XSendEvent(_ecore_x_disp, root, False,
1584               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1585    if (_ecore_xlib_sync) ecore_x_sync();
1586 }
1587 
1588 EAPI void
ecore_x_netwm_desktop_request_send(Ecore_X_Window win,Ecore_X_Window root,unsigned int desktop)1589 ecore_x_netwm_desktop_request_send(Ecore_X_Window win,
1590                                    Ecore_X_Window root,
1591                                    unsigned int desktop)
1592 {
1593    XEvent xev = { 0 };
1594 
1595    if (!win)
1596      return;
1597 
1598    LOGFN;
1599    if (!root)
1600      root = DefaultRootWindow(_ecore_x_disp);
1601 
1602    xev.xclient.type = ClientMessage;
1603    xev.xclient.serial = 0;
1604    xev.xclient.send_event = True;
1605    xev.xclient.display = _ecore_x_disp;
1606    xev.xclient.window = win;
1607    xev.xclient.format = 32;
1608    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_DESKTOP;
1609    xev.xclient.data.l[0] = desktop;
1610 
1611    XSendEvent(_ecore_x_disp, root, False,
1612               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1613    if (_ecore_xlib_sync) ecore_x_sync();
1614 }
1615 
1616 EAPI void
ecore_x_netwm_moveresize_request_send(Ecore_X_Window win,int x,int y,Ecore_X_Netwm_Direction direction,unsigned int button)1617 ecore_x_netwm_moveresize_request_send(Ecore_X_Window win,
1618                                       int x,
1619                                       int y,
1620                                       Ecore_X_Netwm_Direction direction,
1621                                       unsigned int button)
1622 {
1623    XEvent xev = { 0 };
1624 
1625    if (!win)
1626      return;
1627 
1628    LOGFN;
1629    xev.xclient.window = win;
1630    xev.xclient.type = ClientMessage;
1631    xev.xclient.message_type = ECORE_X_ATOM_NET_WM_MOVERESIZE;
1632    xev.xclient.format = 32;
1633    xev.xclient.data.l[0] = x;
1634    xev.xclient.data.l[1] = y;
1635    xev.xclient.data.l[2] = direction;
1636    xev.xclient.data.l[3] = button;
1637    xev.xclient.data.l[4] = 1;
1638 
1639    XSendEvent(_ecore_x_disp, win, False,
1640               SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1641    if (_ecore_xlib_sync) ecore_x_sync();
1642 }
1643 
1644 int
_ecore_x_netwm_startup_info_begin(Ecore_X_Window win EINA_UNUSED,char * data EINA_UNUSED)1645 _ecore_x_netwm_startup_info_begin(Ecore_X_Window win EINA_UNUSED,
1646                                   char *data EINA_UNUSED)
1647 {
1648 #if 0
1649    Ecore_X_Startup_Info *info;
1650    unsigned char *exists = 0;
1651 
1652    if (!startup_info)
1653      return 0;
1654 
1655    info = eina_hash_find(startup_info, (void *)win);
1656    if (info)
1657      {
1658         exists = 1;
1659         WRN("Already got info for win: 0x%x", win);
1660         _ecore_x_netwm_startup_info_free(info);
1661      }
1662 
1663    info = calloc(1, sizeof(Ecore_X_Startup_Info));
1664    if (!info)
1665      return 0;
1666 
1667    info->win = win;
1668    info->length = 0;
1669    info->buffer_size = 161;
1670    info->buffer = calloc(info->buffer_size, sizeof(char));
1671    if (!info->buffer)
1672      {
1673         _ecore_x_netwm_startup_info_free(info);
1674         return 0;
1675      }
1676 
1677    memcpy(info->buffer, data, 20);
1678    info->length += 20;
1679    info->buffer[info->length] = 0;
1680    if (exists)
1681      eina_hash_modify(startup_info, (void *)info->win, info);
1682    else
1683      eina_hash_add(startup_info, (void *)info->win, info);
1684 
1685    if (strlen(info->buffer) != 20)
1686      /* We have a '\0' in there, the message is done */
1687      _ecore_x_netwm_startup_info_process(info);
1688 
1689 #endif /* if 0 */
1690    return 1;
1691 }
1692 
1693 int
_ecore_x_netwm_startup_info(Ecore_X_Window win EINA_UNUSED,char * data EINA_UNUSED)1694 _ecore_x_netwm_startup_info(Ecore_X_Window win EINA_UNUSED,
1695                             char *data EINA_UNUSED)
1696 {
1697 #if 0
1698    Ecore_X_Startup_Info *info;
1699    char *p;
1700 
1701    if (!startup_info)
1702      return 0;
1703 
1704    info = eina_hash_find(startup_info, (void *)win);
1705    if (!info)
1706      return 0;
1707 
1708    if ((info->length + 20) > info->buffer_size)
1709      {
1710         info->buffer_size += 160;
1711         info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
1712         if (!info->buffer)
1713           {
1714              eina_hash_del(startup_info, (void *)info->win);
1715              _ecore_x_netwm_startup_info_free(info);
1716              return 0;
1717           }
1718      }
1719 
1720    memcpy(info->buffer + info->length, data, 20);
1721    p = info->buffer + info->length;
1722    info->length += 20;
1723    info->buffer[info->length] = 0;
1724    if (strlen(p) != 20)
1725      /* We have a '\0' in there, the message is done */
1726      _ecore_x_netwm_startup_info_process(info);
1727 
1728 #endif /* if 0 */
1729    return 1;
1730 }
1731 
1732 /*
1733  * Set UTF-8 string property
1734  */
1735 static void
_ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,Ecore_X_Atom atom,const char * str)1736 _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
1737                                      Ecore_X_Atom atom,
1738                                      const char *str)
1739 {
1740    XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8,
1741                    PropModeReplace, (unsigned char *)str, strlen(str));
1742    if (_ecore_xlib_sync) ecore_x_sync();
1743 }
1744 
1745 /*
1746  * Get UTF-8 string property
1747  */
1748 static char *
_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,Ecore_X_Atom atom)1749 _ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
1750                                      Ecore_X_Atom atom)
1751 {
1752    char *str;
1753    unsigned char *prop_ret;
1754    Atom type_ret;
1755    unsigned long bytes_after, num_ret;
1756    int format_ret;
1757 
1758    str = NULL;
1759    prop_ret = NULL;
1760    XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
1761                       ECORE_X_ATOM_UTF8_STRING, &type_ret,
1762                       &format_ret, &num_ret, &bytes_after, &prop_ret);
1763    if (_ecore_xlib_sync) ecore_x_sync();
1764    if (prop_ret && num_ret > 0 && format_ret == 8)
1765      {
1766         str = malloc(num_ret + 1);
1767         if (str)
1768           {
1769              memcpy(str, prop_ret, num_ret);
1770              str[num_ret] = '\0';
1771           }
1772      }
1773 
1774    if (prop_ret)
1775      XFree(prop_ret);
1776 
1777    return str;
1778 }
1779 
1780 #if 0 /* Unused */
1781 /*
1782  * Process startup info
1783  */
1784 static int
1785 _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
1786 {
1787    Ecore_X_Event_Startup_Sequence *e;
1788    int event;
1789    char *p;
1790 
1791    p = strchr(info->buffer, ':');
1792    if (!p)
1793      {
1794         eina_hash_del(startup_info, (void *)info->win);
1795         _ecore_x_netwm_startup_info_free(info);
1796         return 0;
1797      }
1798 
1799    *p = 0;
1800    if (!strcmp(info->buffer, "new"))
1801      {
1802         if (info->init)
1803           event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
1804         else
1805           event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
1806 
1807         info->init = 1;
1808      }
1809    else if (!strcmp(info->buffer, "change"))
1810      event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
1811    else if (!strcmp(info->buffer, "remove"))
1812      event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
1813    else
1814      {
1815         eina_hash_del(startup_info, (void *)info->win);
1816         _ecore_x_netwm_startup_info_free(info);
1817         return 0;
1818      }
1819 
1820    p++;
1821 
1822    if (!_ecore_x_netwm_startup_info_parse(info, p))
1823      {
1824         eina_hash_del(startup_info, (void *)info->win);
1825         _ecore_x_netwm_startup_info_free(info);
1826         return 0;
1827      }
1828 
1829    if (info->init)
1830      {
1831         e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
1832         if (!e)
1833           {
1834              eina_hash_del(startup_info, (void *)info->win);
1835              _ecore_x_netwm_startup_info_free(info);
1836              return 0;
1837           }
1838 
1839         e->win = info->win;
1840         ecore_event_add(event, e, NULL, NULL);
1841      }
1842 
1843    if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
1844      {
1845         eina_hash_del(startup_info, (void *)info->win);
1846         _ecore_x_netwm_startup_info_free(info);
1847      }
1848    else
1849      {
1850         /* Discard buffer */
1851         info->length = 0;
1852         info->buffer[0] = 0;
1853      }
1854 
1855    return 1;
1856 }
1857 
1858 /*
1859  * Parse startup info
1860  */
1861 static int
1862 _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
1863                                   char *data)
1864 {
1865    while (*data)
1866      {
1867         int in_quot_sing, in_quot_dbl, escaped;
1868         char *p, *pp;
1869         char *key;
1870         char value[1024];
1871 
1872         /* Skip space */
1873         while (*data == ' ')
1874           data++;
1875         /* Get key */
1876         key = data;
1877         data = strchr(key, '=');
1878         if (!data)
1879           return 0;
1880 
1881         *data = 0;
1882         data++;
1883 
1884         /* Get value */
1885         p = data;
1886         pp = value;
1887         in_quot_dbl = 0;
1888         in_quot_sing = 0;
1889         escaped = 0;
1890         while (*p)
1891           {
1892              if ((pp - value) >= 1024)
1893                return 0;
1894 
1895              if (escaped)
1896                {
1897                   *pp = *p;
1898                   pp++;
1899                   escaped = 0;
1900                }
1901              else if (in_quot_sing)
1902                {
1903                   if (*p == '\\')
1904                     escaped = 1;
1905                   else if (*p == '\'')
1906                     in_quot_sing = 0;
1907                   else
1908                     {
1909                        *pp = *p;
1910                        pp++;
1911                     }
1912                }
1913              else if (in_quot_dbl)
1914                {
1915                   if (*p == '\\')
1916                     escaped = 1;
1917                   else if (*p == '\"')
1918                     in_quot_dbl = 0;
1919                   else
1920                     {
1921                        *pp = *p;
1922                        pp++;
1923                     }
1924                }
1925              else
1926                {
1927                   if (*p == '\\')
1928                     escaped = 1;
1929                   else if (*p == '\'')
1930                     in_quot_sing = 1;
1931                   else if (*p == '\"')
1932                     in_quot_dbl = 1;
1933                   else if (*p == ' ')
1934                     break;
1935                   else
1936                     {
1937                        *pp = *p;
1938                        pp++;
1939                     }
1940                }
1941 
1942              p++;
1943           }
1944         if ((in_quot_dbl) || (in_quot_sing))
1945           return 0;
1946 
1947         data = p;
1948         *pp = 0;
1949 
1950         /* Parse info */
1951         if (!strcmp(key, "ID"))
1952           {
1953              if ((info->id) && (strcmp(info->id, value)))
1954                return 0;
1955 
1956              info->id = strdup(value);
1957              p = strstr(value, "_TIME");
1958              if (p)
1959                info->timestamp = atoi(p + 5);
1960           }
1961         else if (!strcmp(key, "NAME"))
1962           {
1963              if (info->name)
1964                free(info->name);
1965 
1966              info->name = strdup(value);
1967           }
1968         else if (!strcmp(key, "SCREEN"))
1969           info->screen = atoi(value);
1970         else if (!strcmp(key, "BIN"))
1971           {
1972              if (info->bin)
1973                free(info->bin);
1974 
1975              info->bin = strdup(value);
1976           }
1977         else if (!strcmp(key, "ICON"))
1978           {
1979              if (info->icon)
1980                free(info->icon);
1981 
1982              info->icon = strdup(value);
1983           }
1984         else if (!strcmp(key, "DESKTOP"))
1985           info->desktop = atoi(value);
1986         else if (!strcmp(key, "TIMESTAMP"))
1987           {
1988              if (!info->timestamp)
1989                info->timestamp = atoi(value);
1990           }
1991         else if (!strcmp(key, "DESCRIPTION"))
1992           {
1993              if (info->description)
1994                free(info->description);
1995 
1996              info->description = strdup(value);
1997           }
1998         else if (!strcmp(key, "WMCLASS"))
1999           {
2000              if (info->wmclass)
2001                free(info->wmclass);
2002 
2003              info->wmclass = strdup(value);
2004           }
2005         else if (!strcmp(key, "SILENT"))
2006           info->silent = atoi(value);
2007         else
2008           ERR("Ecore X Sequence, Unknown: %s=%s", key, value);
2009      }
2010    if (!info->id)
2011      return 0;
2012 
2013    return 1;
2014 }
2015 
2016 #endif /* if 0 */
2017 
2018 /*
2019  * Free startup info struct
2020  */
2021 static void
_ecore_x_netwm_startup_info_free(void * data)2022 _ecore_x_netwm_startup_info_free(void *data)
2023 {
2024    Ecore_X_Startup_Info *info;
2025 
2026    info = data;
2027    if (!info)
2028      return;
2029 
2030    if (info->buffer)
2031      free(info->buffer);
2032 
2033    if (info->id)
2034      free(info->id);
2035 
2036    if (info->name)
2037      free(info->name);
2038 
2039    if (info->bin)
2040      free(info->bin);
2041 
2042    if (info->icon)
2043      free(info->icon);
2044 
2045    if (info->description)
2046      free(info->description);
2047 
2048    if (info->wmclass)
2049      free(info->wmclass);
2050 
2051    free(info);
2052 }
2053 
2054 /*
2055  * Is screen composited?
2056  */
2057 EAPI Eina_Bool
ecore_x_screen_is_composited(int screen)2058 ecore_x_screen_is_composited(int screen)
2059 {
2060    Ecore_X_Window win;
2061    Ecore_X_Atom atom;
2062    char buf[32];
2063 
2064    LOGFN;
2065    snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
2066    atom = XInternAtom(_ecore_x_disp, buf, True);
2067    if (atom == None) return EINA_FALSE;
2068    win = XGetSelectionOwner(_ecore_x_disp, atom);
2069    if (_ecore_xlib_sync) ecore_x_sync();
2070    return (win != None) ? EINA_TRUE : EINA_FALSE;
2071 }
2072 
2073 EAPI void
ecore_x_screen_is_composited_set(int screen,Ecore_X_Window win)2074 ecore_x_screen_is_composited_set(int screen,
2075                                  Ecore_X_Window win)
2076 {
2077    Ecore_X_Atom atom;
2078    char buf[32];
2079 
2080    LOGFN;
2081    snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
2082    atom = XInternAtom(_ecore_x_disp, buf, False);
2083    if (atom == None) return;
2084    XSetSelectionOwner(_ecore_x_disp, atom, win, _ecore_x_event_last_time);
2085    if (_ecore_xlib_sync) ecore_x_sync();
2086 }
2087 
2088