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