Fix a lot of unimportant memleaks caused by a CRIT_ERR
[monky] / src / x11.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Any original torsmo code is licensed under the BSD license
4  *
5  * All code written since the fork of torsmo is licensed under the GPL
6  *
7  * Please see COPYING for details
8  *
9  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
10  * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
11  *      (see AUTHORS)
12  * All rights reserved.
13  *
14  * This program is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  *
26  */
27
28 #include "config.h"
29 #include "conky.h"
30 #include "logging.h"
31 #include "common.h"
32
33 #include "x11.h"
34 #include <X11/Xlib.h>
35 #include <X11/Xatom.h>
36 #include <X11/Xmd.h>
37 #include <X11/Xutil.h>
38 #ifdef IMLIB2
39 #include "imlib2.h"
40 #endif /* IMLIB2 */
41
42 #ifdef XFT
43 #include <X11/Xft/Xft.h>
44 int use_xft = 0;
45 #endif
46
47 #ifdef HAVE_XDBE
48 int use_xdbe;
49 #endif
50
51 /* some basic X11 stuff */
52 Display *display = NULL;
53 int display_width;
54 int display_height;
55 int screen;
56 static int set_transparent;
57 static int background_colour;
58
59 /* workarea from _NET_WORKAREA, this is where window / text is aligned */
60 int workarea[4];
61
62 /* Window stuff */
63 struct conky_window window;
64
65 /* local prototypes */
66 static void update_workarea(void);
67 static Window find_desktop_window(Window *p_root, Window *p_desktop);
68 static Window find_subwindow(Window win, int w, int h);
69
70 /* X11 initializer */
71 void init_X11(const char *disp)
72 {
73         if (!display) {
74                 if ((display = XOpenDisplay(disp)) == NULL) {
75                         CRIT_ERR(NULL, NULL, "can't open display: %s", XDisplayName(0));
76                 }
77         }
78
79         screen = DefaultScreen(display);
80         display_width = DisplayWidth(display, screen);
81         display_height = DisplayHeight(display, screen);
82
83         get_x11_desktop_info(display, 0);
84
85         update_workarea();
86 }
87
88 static void update_workarea(void)
89 {
90         /* default work area is display */
91         workarea[0] = 0;
92         workarea[1] = 0;
93         workarea[2] = display_width;
94         workarea[3] = display_height;
95 }
96
97 /* Find root window and desktop window.
98  * Return desktop window on success,
99  * and set root and desktop byref return values.
100  * Return 0 on failure. */
101 static Window find_desktop_window(Window *p_root, Window *p_desktop)
102 {
103         Atom type;
104         int format, i;
105         unsigned long nitems, bytes;
106         unsigned int n;
107         Window root = RootWindow(display, screen);
108         Window win = root;
109         Window troot, parent, *children;
110         unsigned char *buf = NULL;
111
112         if (!p_root || !p_desktop) {
113                 return 0;
114         }
115
116         /* some window managers set __SWM_VROOT to some child of root window */
117
118         XQueryTree(display, root, &troot, &parent, &children, &n);
119         for (i = 0; i < (int) n; i++) {
120                 if (XGetWindowProperty(display, children[i], ATOM(__SWM_VROOT), 0, 1,
121                                 False, XA_WINDOW, &type, &format, &nitems, &bytes, &buf)
122                                 == Success && type == XA_WINDOW) {
123                         win = *(Window *) buf;
124                         XFree(buf);
125                         XFree(children);
126                         fprintf(stderr,
127                                 PACKAGE_NAME": desktop window (%lx) found from __SWM_VROOT property\n",
128                                 win);
129                         fflush(stderr);
130                         *p_root = win;
131                         *p_desktop = win;
132                         return win;
133                 }
134
135                 if (buf) {
136                         XFree(buf);
137                         buf = 0;
138                 }
139         }
140         XFree(children);
141
142         /* get subwindows from root */
143         win = find_subwindow(root, -1, -1);
144
145         update_workarea();
146
147         win = find_subwindow(win, workarea[2], workarea[3]);
148
149         if (buf) {
150                 XFree(buf);
151                 buf = 0;
152         }
153
154         if (win != root) {
155                 fprintf(stderr,
156                         PACKAGE_NAME": desktop window (%lx) is subwindow of root window (%lx)\n",
157                         win, root);
158         } else {
159                 fprintf(stderr, PACKAGE_NAME": desktop window (%lx) is root window\n", win);
160         }
161
162         fflush(stderr);
163
164         *p_root = root;
165         *p_desktop = win;
166
167         return win;
168 }
169
170 /* sets background to ParentRelative for the Window and all parents */
171 void set_transparent_background(Window win)
172 {
173         static int colour_set = -1;
174
175         if (set_transparent) {
176                 Window parent = win;
177                 unsigned int i;
178
179                 for (i = 0; i < 50 && parent != RootWindow(display, screen); i++) {
180                         Window r, *children;
181                         unsigned int n;
182
183                         XSetWindowBackgroundPixmap(display, parent, ParentRelative);
184
185                         XQueryTree(display, parent, &r, &parent, &children, &n);
186                         XFree(children);
187                 }
188         } else if (colour_set != background_colour) {
189                 XSetWindowBackground(display, win, background_colour);
190                 colour_set = background_colour;
191         }
192         // XClearWindow(display, win); not sure why this was here
193 }
194
195 void destroy_window(void)
196 {
197         if(window.xftdraw) {
198                 XftDrawDestroy(window.xftdraw);
199         }
200         if(window.gc) {
201                 XFreeGC(display, window.gc);
202         }
203         memset(&window, 0, sizeof(struct conky_window));
204 }
205
206 void init_window(int own_window, int w, int h, int set_trans, int back_colour,
207                 char **argv, int argc)
208 {
209         /* There seems to be some problems with setting transparent background
210          * (on fluxbox this time). It doesn't happen always and I don't know why it
211          * happens but I bet the bug is somewhere here. */
212         set_transparent = set_trans;
213         background_colour = back_colour;
214
215 #ifdef OWN_WINDOW
216         if (own_window) {
217                 if (!find_desktop_window(&window.root, &window.desktop)) {
218                         return;
219                 }
220
221                 if (window.type == TYPE_OVERRIDE) {
222
223                         /* An override_redirect True window.
224                          * No WM hints or button processing needed. */
225                         XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0,
226                                 Always, 0L, 0L, False, StructureNotifyMask | ExposureMask, 0L,
227                                 True, 0, 0 };
228
229                         /* Parent is desktop window (which might be a child of root) */
230                         window.window = XCreateWindow(display, window.desktop, window.x,
231                                 window.y, w, h, 0, CopyFromParent, InputOutput, CopyFromParent,
232                                 CWBackPixel | CWOverrideRedirect, &attrs);
233
234                         XLowerWindow(display, window.window);
235
236                         fprintf(stderr, PACKAGE_NAME": window type - override\n");
237                         fflush(stderr);
238                 } else { /* window.type != TYPE_OVERRIDE */
239
240                         /* A window managed by the window manager.
241                          * Process hints and buttons. */
242                         XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0,
243                                 Always, 0L, 0L, False, StructureNotifyMask | ExposureMask |
244                                 ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 };
245
246                         XClassHint classHint;
247                         XWMHints wmHint;
248                         Atom xa;
249
250                         if (window.type == TYPE_DOCK) {
251                                 window.x = window.y = 0;
252                         }
253                         /* Parent is root window so WM can take control */
254                         window.window = XCreateWindow(display, window.root, window.x,
255                                 window.y, w, h, 0, CopyFromParent, InputOutput, CopyFromParent,
256                                 CWBackPixel | CWOverrideRedirect, &attrs);
257
258                         classHint.res_name = window.class_name;
259                         classHint.res_class = classHint.res_name;
260
261                         wmHint.flags = InputHint | StateHint;
262                         /* allow decorated windows to be given input focus by WM */
263                         wmHint.input =
264                                 TEST_HINT(window.hints, HINT_UNDECORATED) ? False : True;
265                         if (window.type == TYPE_DOCK || window.type == TYPE_PANEL) {
266                                 wmHint.initial_state = WithdrawnState;
267                         } else {
268                                 wmHint.initial_state = NormalState;
269                         }
270
271                         XmbSetWMProperties(display, window.window, window.title, NULL, argv,
272                                 argc, NULL, &wmHint, &classHint);
273
274                         /* Sets an empty WM_PROTOCOLS property */
275                         XSetWMProtocols(display, window.window, NULL, 0);
276
277                         /* Set window type */
278                         if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) {
279                                 Atom prop;
280
281                                 switch (window.type) {
282                                         case TYPE_DESKTOP:
283                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP);
284                                                 fprintf(stderr, PACKAGE_NAME": window type - desktop\n");
285                                                 fflush(stderr);
286                                                 break;
287                                         case TYPE_DOCK:
288                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
289                                                 fprintf(stderr, PACKAGE_NAME": window type - dock\n");
290                                                 fflush(stderr);
291                                                 break;
292                                         case TYPE_PANEL:
293                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
294                                                 fprintf(stderr, PACKAGE_NAME": window type - panel\n");
295                                                 fflush(stderr);
296                                                 break;
297                                         case TYPE_NORMAL:
298                                         default:
299                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
300                                                 fprintf(stderr, PACKAGE_NAME": window type - normal\n");
301                                                 fflush(stderr);
302                                                 break;
303                                 }
304                                 XChangeProperty(display, window.window, xa, XA_ATOM, 32,
305                                         PropModeReplace, (unsigned char *) &prop, 1);
306                         }
307
308                         /* Set desired hints */
309
310                         /* Window decorations */
311                         if (TEST_HINT(window.hints, HINT_UNDECORATED)) {
312                                 /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n");
313                                 fflush(stderr); */
314
315                                 xa = ATOM(_MOTIF_WM_HINTS);
316                                 if (xa != None) {
317                                         long prop[5] = { 2, 0, 0, 0, 0 };
318                                         XChangeProperty(display, window.window, xa, xa, 32,
319                                                 PropModeReplace, (unsigned char *) prop, 5);
320                                 }
321                         }
322
323                         /* Below other windows */
324                         if (TEST_HINT(window.hints, HINT_BELOW)) {
325                                 /* fprintf(stderr, PACKAGE_NAME": hint - below\n");
326                                 fflush(stderr); */
327
328                                 xa = ATOM(_WIN_LAYER);
329                                 if (xa != None) {
330                                         long prop = 0;
331
332                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
333                                                 PropModeAppend, (unsigned char *) &prop, 1);
334                                 }
335
336                                 xa = ATOM(_NET_WM_STATE);
337                                 if (xa != None) {
338                                         Atom xa_prop = ATOM(_NET_WM_STATE_BELOW);
339
340                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
341                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
342                                 }
343                         }
344
345                         /* Above other windows */
346                         if (TEST_HINT(window.hints, HINT_ABOVE)) {
347                                 /* fprintf(stderr, PACKAGE_NAME": hint - above\n");
348                                 fflush(stderr); */
349
350                                 xa = ATOM(_WIN_LAYER);
351                                 if (xa != None) {
352                                         long prop = 6;
353
354                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
355                                                 PropModeAppend, (unsigned char *) &prop, 1);
356                                 }
357
358                                 xa = ATOM(_NET_WM_STATE);
359                                 if (xa != None) {
360                                         Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE);
361
362                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
363                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
364                                 }
365                         }
366
367                         /* Sticky */
368                         if (TEST_HINT(window.hints, HINT_STICKY)) {
369                                 /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n");
370                                 fflush(stderr); */
371
372                                 xa = ATOM(_NET_WM_DESKTOP);
373                                 if (xa != None) {
374                                         CARD32 xa_prop = 0xFFFFFFFF;
375
376                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
377                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
378                                 }
379
380                                 xa = ATOM(_NET_WM_STATE);
381                                 if (xa != None) {
382                                         Atom xa_prop = ATOM(_NET_WM_STATE_STICKY);
383
384                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
385                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
386                                 }
387                         }
388
389                         /* Skip taskbar */
390                         if (TEST_HINT(window.hints, HINT_SKIP_TASKBAR)) {
391                                 /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n");
392                                 fflush(stderr); */
393
394                                 xa = ATOM(_NET_WM_STATE);
395                                 if (xa != None) {
396                                         Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR);
397
398                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
399                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
400                                 }
401                         }
402
403                         /* Skip pager */
404                         if (TEST_HINT(window.hints, HINT_SKIP_PAGER)) {
405                                 /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n");
406                                 fflush(stderr); */
407
408                                 xa = ATOM(_NET_WM_STATE);
409                                 if (xa != None) {
410                                         Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER);
411
412                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
413                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
414                                 }
415                         }
416                 } /* else { window.type != TYPE_OVERRIDE */
417
418                 fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n",
419                         window.window);
420                 fflush(stderr);
421
422                 XMapWindow(display, window.window);
423
424         } else /* if (own_window) { */
425 #endif
426                 /* root / desktop window */
427         {
428                 XWindowAttributes attrs;
429
430                 if (!window.window) {
431                         window.window = find_desktop_window(&window.root, &window.desktop);
432                 }
433
434                 if (XGetWindowAttributes(display, window.window, &attrs)) {
435                         window.width = attrs.width;
436                         window.height = attrs.height;
437                 }
438
439                 fprintf(stderr, PACKAGE_NAME": drawing to desktop window\n");
440         }
441
442         /* Drawable is same as window. This may be changed by double buffering. */
443         window.drawable = window.window;
444
445 #ifdef HAVE_XDBE
446         if (use_xdbe) {
447                 int major, minor;
448
449                 if (!XdbeQueryExtension(display, &major, &minor)) {
450                         use_xdbe = 0;
451                 } else {
452                         window.back_buffer = XdbeAllocateBackBufferName(display,
453                                 window.window, XdbeBackground);
454                         if (window.back_buffer != None) {
455                                 window.drawable = window.back_buffer;
456                                 fprintf(stderr, PACKAGE_NAME": drawing to double buffer\n");
457                         } else {
458                                 use_xdbe = 0;
459                         }
460                 }
461                 if (!use_xdbe) {
462                         ERR("failed to set up double buffer");
463                 }
464         }
465         if (!use_xdbe) {
466                 fprintf(stderr, PACKAGE_NAME": drawing to single buffer\n");
467         }
468 #endif
469         window.visual = DefaultVisual(display, DefaultScreen(display));
470         window.colourmap = DefaultColormap(display, DefaultScreen(display));
471 #ifdef IMLIB2
472         {
473                 cimlib_init(display, window.drawable, window.visual, window.colourmap);
474         }
475 #endif /* IMLIB2 */
476         XFlush(display);
477
478         /* set_transparent_background(window.window);
479          * must be done after double buffer stuff? */
480 #ifdef OWN_WINDOW
481         /* if (own_window) {
482                 set_transparent_background(window.window);
483                 XClearWindow(display, window.window);
484         } */
485 #endif
486
487         XSelectInput(display, window.window, ExposureMask | PropertyChangeMask
488 #ifdef OWN_WINDOW
489                 | (own_window ? (StructureNotifyMask |
490                 ButtonPressMask | ButtonReleaseMask) : 0)
491 #endif
492                 );
493 }
494
495 static Window find_subwindow(Window win, int w, int h)
496 {
497         unsigned int i, j;
498         Window troot, parent, *children;
499         unsigned int n;
500
501         /* search subwindows with same size as display or work area */
502
503         for (i = 0; i < 10; i++) {
504                 XQueryTree(display, win, &troot, &parent, &children, &n);
505
506                 for (j = 0; j < n; j++) {
507                         XWindowAttributes attrs;
508
509                         if (XGetWindowAttributes(display, children[j], &attrs)) {
510                                 /* Window must be mapped and same size as display or
511                                  * work space */
512                                 if (attrs.map_state != 0 && ((attrs.width == display_width
513                                                 && attrs.height == display_height)
514                                                 || (attrs.width == w && attrs.height == h))) {
515                                         win = children[j];
516                                         break;
517                                 }
518                         }
519                 }
520
521                 XFree(children);
522                 if (j == n) {
523                         break;
524                 }
525         }
526
527         return win;
528 }
529
530 long get_x11_color(const char *name)
531 {
532         XColor color;
533
534         color.pixel = 0;
535         if (!XParseColor(display, DefaultColormap(display, screen), name, &color)) {
536                 /* lets check if it's a hex colour with the # missing in front
537                  * if yes, then do something about it */
538                 char newname[DEFAULT_TEXT_BUFFER_SIZE];
539
540                 newname[0] = '#';
541                 strncpy(&newname[1], name, DEFAULT_TEXT_BUFFER_SIZE - 1);
542                 /* now lets try again */
543                 if (!XParseColor(display, DefaultColormap(display, screen), &newname[0],
544                                 &color)) {
545                         ERR("can't parse X color '%s'", name);
546                         return 0xFF00FF;
547                 }
548         }
549         if (!XAllocColor(display, DefaultColormap(display, screen), &color)) {
550                 ERR("can't allocate X color '%s'", name);
551         }
552
553         return (long) color.pixel;
554 }
555
556 void create_gc(void)
557 {
558         XGCValues values;
559
560         values.graphics_exposures = 0;
561         values.function = GXcopy;
562         window.gc = XCreateGC(display, window.drawable,
563                 GCFunction | GCGraphicsExposures, &values);
564 }
565
566 //Get current desktop number
567 static inline void get_x11_desktop_current(Display *current_display, Window root, Atom atom)
568 {
569         Atom actual_type;
570         int actual_format;
571         unsigned long nitems;
572         unsigned long bytes_after;
573         unsigned char *prop = NULL;
574         struct information *current_info = &info;
575
576         if ( (XGetWindowProperty( current_display, root, atom,
577                                   0, 1L, False, XA_CARDINAL,
578                                   &actual_type, &actual_format, &nitems,
579                                   &bytes_after, &prop ) == Success ) &&
580              (actual_type == XA_CARDINAL) &&
581              (nitems == 1L) && (actual_format == 32) ) {
582           current_info->x11.desktop.current = prop[0]+1;
583         }
584         if(prop) {
585           XFree(prop);
586         }
587 }
588
589 //Get total number of available desktops
590 static inline void get_x11_desktop_number(Display *current_display, Window root, Atom atom)
591 {
592         Atom actual_type;
593         int actual_format;
594         unsigned long nitems;
595         unsigned long bytes_after;
596         unsigned char *prop = NULL;
597         struct information *current_info = &info;
598
599         if ( (XGetWindowProperty( current_display, root, atom,
600                                   0, 1L, False, XA_CARDINAL,
601                                   &actual_type, &actual_format, &nitems,
602                                   &bytes_after, &prop ) == Success ) &&
603              (actual_type == XA_CARDINAL) &&
604              (nitems == 1L) && (actual_format == 32) ) {
605           current_info->x11.desktop.number = prop[0];
606         }
607         if(prop) {
608           XFree(prop);
609         }
610 }
611
612 //Get all desktop names
613 static inline void get_x11_desktop_names(Display *current_display, Window root, Atom atom)
614 {
615         Atom actual_type;
616         int actual_format;
617         unsigned long nitems;
618         unsigned long bytes_after;
619         unsigned char *prop = NULL;
620         struct information *current_info = &info;
621
622         if ( (XGetWindowProperty( current_display, root, atom,
623                                   0, (~0L), False, ATOM(UTF8_STRING),
624                                   &actual_type, &actual_format, &nitems,
625                                   &bytes_after, &prop ) == Success ) &&
626              (actual_type == ATOM(UTF8_STRING)) &&
627              (nitems > 0L) && (actual_format == 8) ) {
628
629           if(current_info->x11.desktop.all_names) {
630             free(current_info->x11.desktop.all_names);
631             current_info->x11.desktop.all_names = NULL;
632           }
633           current_info->x11.desktop.all_names = malloc(nitems*sizeof(char));
634           memcpy(current_info->x11.desktop.all_names, prop, nitems);
635           current_info->x11.desktop.nitems = nitems;
636         }
637         if(prop) {
638           XFree(prop);
639         }
640 }
641
642 //Get current desktop name
643 static inline void get_x11_desktop_current_name(char *names)
644 {
645         struct information *current_info = &info;
646         unsigned int i = 0, j = 0;
647         int k = 0;
648
649         while ( i < current_info->x11.desktop.nitems ) {
650           if ( names[i++] == '\0' ) {
651             if ( ++k == current_info->x11.desktop.current ) {
652               if (current_info->x11.desktop.name) {
653                 free(current_info->x11.desktop.name);
654                 current_info->x11.desktop.name = NULL;
655               }
656               current_info->x11.desktop.name = malloc((i-j)*sizeof(char));
657               //desktop names can be empty but should always be not null
658               strcpy( current_info->x11.desktop.name, (char *)&names[j] );
659               break;
660             }
661             j = i;
662           }
663         }
664 }
665
666 void get_x11_desktop_info(Display *current_display, Atom atom)
667 {
668         Window root;
669         static Atom atom_current, atom_number, atom_names;
670         struct information *current_info = &info;
671         XWindowAttributes window_attributes;
672
673         root = RootWindow(current_display, current_info->x11.monitor.current);
674
675         //Check if we initialise else retrieve changed property
676         if (atom == 0) {
677           atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True);
678           atom_number  = XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True);
679           atom_names   = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True);
680           get_x11_desktop_current(current_display, root, atom_current);
681           get_x11_desktop_number(current_display, root, atom_number);
682           get_x11_desktop_names(current_display, root, atom_names);
683           get_x11_desktop_current_name(current_info->x11.desktop.all_names);
684
685           //Set the PropertyChangeMask on the root window, if not set
686           XGetWindowAttributes(display, root, &window_attributes);
687           if (!(window_attributes.your_event_mask & PropertyChangeMask)) {
688             XSetWindowAttributes attributes;
689             attributes.event_mask = window_attributes.your_event_mask | PropertyChangeMask;
690             XChangeWindowAttributes(display, root, CWEventMask, &attributes);
691             XGetWindowAttributes(display, root, &window_attributes);
692           }
693         } else {
694           if (atom == atom_current) {
695             get_x11_desktop_current(current_display, root, atom_current);
696             get_x11_desktop_current_name(current_info->x11.desktop.all_names);
697           } else if (atom == atom_number) {
698             get_x11_desktop_number(current_display, root, atom_number);
699           } else if (atom == atom_names) {
700             get_x11_desktop_names(current_display, root, atom_names);
701             get_x11_desktop_current_name(current_info->x11.desktop.all_names);
702           }
703         }
704 }
705
706 void update_x11info(void)
707 {
708         struct information *current_info = &info;
709         current_info->x11.monitor.number = XScreenCount(display);
710         current_info->x11.monitor.current = XDefaultScreen(display);
711 }
712
713 #ifdef OWN_WINDOW
714 /* reserve window manager space */
715 void set_struts(int sidenum)
716 {
717         Atom strut;
718         if ((strut = ATOM(_NET_WM_STRUT)) != None) {
719                 /* reserve space at left, right, top, bottom */
720                 signed long sizes[12] = {0};
721                 int i;
722
723                 /* define strut depth */
724                 switch (sidenum) {
725                         case 0:
726                         {
727                                 /* left side */
728                                 sizes[0] = window.x + window.width;
729                                 break;
730                         }
731                         case 1:
732                         {
733                                 /* right side */
734                                 sizes[1] = display_width - window.x;
735                                 break;
736                         }
737                         case 2:
738                         {
739                                 /* top side */
740                                 sizes[2] = window.y + window.height;
741                                 break;
742                         }
743                         case 3:
744                         {
745                                 /* bottom side */
746                                 sizes[3] = display_height - window.y;
747                                 break;
748                         }
749                 }
750
751                 /* define partial strut length */
752                 if (sidenum <= 1) {
753                         sizes[4 + (sidenum*2)] = window.y;
754                         sizes[5 + (sidenum*2)] = window.y + window.height;
755                 } else if (sidenum <= 3) {
756                         sizes[4 + (sidenum*2)] = window.x;
757                         sizes[5 + (sidenum*2)] = window.x + window.width;
758                 }
759
760                 /* check constraints */
761                 for (i = 0; i < 12; i++) {
762                         if (sizes[i] < 0) {
763                                 sizes[i] = 0;
764                         } else {
765                                 if (i <= 1 || i >= 8) {
766                                         if (sizes[i] > display_width) {
767                                                 sizes[i] = display_width;
768                                         }
769                                 } else {
770                                         if (sizes[i] > display_height) {
771                                                 sizes[i] = display_height;
772                                         }
773                                 }
774                         }
775                 }
776
777                 XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
778                                 PropModeReplace, (unsigned char *) &sizes, 4);
779
780                 if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) {
781                         XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
782                                         PropModeReplace, (unsigned char *) &sizes, 12);
783                 }
784         }
785 }
786 #endif /* OWN_WINDOW */