Fix strange effects on desktop caused by 4a14668772a37b18a9aceb8951ece260084bc96e
[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("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         XFreeGC(display, window.gc);
198         memset(&window, 0, sizeof(struct conky_window));
199 }
200
201 void init_window(int own_window, int w, int h, int set_trans, int back_colour,
202                 char **argv, int argc)
203 {
204         /* There seems to be some problems with setting transparent background
205          * (on fluxbox this time). It doesn't happen always and I don't know why it
206          * happens but I bet the bug is somewhere here. */
207         set_transparent = set_trans;
208         background_colour = back_colour;
209
210 #ifdef OWN_WINDOW
211         if (own_window) {
212                 if (!find_desktop_window(&window.root, &window.desktop)) {
213                         return;
214                 }
215
216                 if (window.type == TYPE_OVERRIDE) {
217
218                         /* An override_redirect True window.
219                          * No WM hints or button processing needed. */
220                         XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0,
221                                 Always, 0L, 0L, False, StructureNotifyMask | ExposureMask, 0L,
222                                 True, 0, 0 };
223
224                         /* Parent is desktop window (which might be a child of root) */
225                         window.window = XCreateWindow(display, window.desktop, window.x,
226                                 window.y, w, h, 0, CopyFromParent, InputOutput, CopyFromParent,
227                                 CWBackPixel | CWOverrideRedirect, &attrs);
228
229                         XLowerWindow(display, window.window);
230
231                         fprintf(stderr, PACKAGE_NAME": window type - override\n");
232                         fflush(stderr);
233                 } else { /* window.type != TYPE_OVERRIDE */
234
235                         /* A window managed by the window manager.
236                          * Process hints and buttons. */
237                         XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0,
238                                 Always, 0L, 0L, False, StructureNotifyMask | ExposureMask |
239                                 ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 };
240
241                         XClassHint classHint;
242                         XWMHints wmHint;
243                         Atom xa;
244
245                         if (window.type == TYPE_DOCK) {
246                                 window.x = window.y = 0;
247                         }
248                         /* Parent is root window so WM can take control */
249                         window.window = XCreateWindow(display, window.root, window.x,
250                                 window.y, w, h, 0, CopyFromParent, InputOutput, CopyFromParent,
251                                 CWBackPixel | CWOverrideRedirect, &attrs);
252
253                         classHint.res_name = window.class_name;
254                         classHint.res_class = classHint.res_name;
255
256                         wmHint.flags = InputHint | StateHint;
257                         /* allow decorated windows to be given input focus by WM */
258                         wmHint.input =
259                                 TEST_HINT(window.hints, HINT_UNDECORATED) ? False : True;
260                         if (window.type == TYPE_DOCK || window.type == TYPE_PANEL) {
261                                 wmHint.initial_state = WithdrawnState;
262                         } else {
263                                 wmHint.initial_state = NormalState;
264                         }
265
266                         XmbSetWMProperties(display, window.window, window.title, NULL, argv,
267                                 argc, NULL, &wmHint, &classHint);
268
269                         /* Sets an empty WM_PROTOCOLS property */
270                         XSetWMProtocols(display, window.window, NULL, 0);
271
272                         /* Set window type */
273                         if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) {
274                                 Atom prop;
275
276                                 switch (window.type) {
277                                         case TYPE_DESKTOP:
278                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP);
279                                                 fprintf(stderr, PACKAGE_NAME": window type - desktop\n");
280                                                 fflush(stderr);
281                                                 break;
282                                         case TYPE_DOCK:
283                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
284                                                 fprintf(stderr, PACKAGE_NAME": window type - dock\n");
285                                                 fflush(stderr);
286                                                 break;
287                                         case TYPE_PANEL:
288                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
289                                                 fprintf(stderr, PACKAGE_NAME": window type - panel\n");
290                                                 fflush(stderr);
291                                                 break;
292                                         case TYPE_NORMAL:
293                                         default:
294                                                 prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
295                                                 fprintf(stderr, PACKAGE_NAME": window type - normal\n");
296                                                 fflush(stderr);
297                                                 break;
298                                 }
299                                 XChangeProperty(display, window.window, xa, XA_ATOM, 32,
300                                         PropModeReplace, (unsigned char *) &prop, 1);
301                         }
302
303                         /* Set desired hints */
304
305                         /* Window decorations */
306                         if (TEST_HINT(window.hints, HINT_UNDECORATED)) {
307                                 /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n");
308                                 fflush(stderr); */
309
310                                 xa = ATOM(_MOTIF_WM_HINTS);
311                                 if (xa != None) {
312                                         long prop[5] = { 2, 0, 0, 0, 0 };
313                                         XChangeProperty(display, window.window, xa, xa, 32,
314                                                 PropModeReplace, (unsigned char *) prop, 5);
315                                 }
316                         }
317
318                         /* Below other windows */
319                         if (TEST_HINT(window.hints, HINT_BELOW)) {
320                                 /* fprintf(stderr, PACKAGE_NAME": hint - below\n");
321                                 fflush(stderr); */
322
323                                 xa = ATOM(_WIN_LAYER);
324                                 if (xa != None) {
325                                         long prop = 0;
326
327                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
328                                                 PropModeAppend, (unsigned char *) &prop, 1);
329                                 }
330
331                                 xa = ATOM(_NET_WM_STATE);
332                                 if (xa != None) {
333                                         Atom xa_prop = ATOM(_NET_WM_STATE_BELOW);
334
335                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
336                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
337                                 }
338                         }
339
340                         /* Above other windows */
341                         if (TEST_HINT(window.hints, HINT_ABOVE)) {
342                                 /* fprintf(stderr, PACKAGE_NAME": hint - above\n");
343                                 fflush(stderr); */
344
345                                 xa = ATOM(_WIN_LAYER);
346                                 if (xa != None) {
347                                         long prop = 6;
348
349                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
350                                                 PropModeAppend, (unsigned char *) &prop, 1);
351                                 }
352
353                                 xa = ATOM(_NET_WM_STATE);
354                                 if (xa != None) {
355                                         Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE);
356
357                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
358                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
359                                 }
360                         }
361
362                         /* Sticky */
363                         if (TEST_HINT(window.hints, HINT_STICKY)) {
364                                 /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n");
365                                 fflush(stderr); */
366
367                                 xa = ATOM(_NET_WM_DESKTOP);
368                                 if (xa != None) {
369                                         CARD32 xa_prop = 0xFFFFFFFF;
370
371                                         XChangeProperty(display, window.window, xa, XA_CARDINAL, 32,
372                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
373                                 }
374
375                                 xa = ATOM(_NET_WM_STATE);
376                                 if (xa != None) {
377                                         Atom xa_prop = ATOM(_NET_WM_STATE_STICKY);
378
379                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
380                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
381                                 }
382                         }
383
384                         /* Skip taskbar */
385                         if (TEST_HINT(window.hints, HINT_SKIP_TASKBAR)) {
386                                 /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n");
387                                 fflush(stderr); */
388
389                                 xa = ATOM(_NET_WM_STATE);
390                                 if (xa != None) {
391                                         Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR);
392
393                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
394                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
395                                 }
396                         }
397
398                         /* Skip pager */
399                         if (TEST_HINT(window.hints, HINT_SKIP_PAGER)) {
400                                 /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n");
401                                 fflush(stderr); */
402
403                                 xa = ATOM(_NET_WM_STATE);
404                                 if (xa != None) {
405                                         Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER);
406
407                                         XChangeProperty(display, window.window, xa, XA_ATOM, 32,
408                                                 PropModeAppend, (unsigned char *) &xa_prop, 1);
409                                 }
410                         }
411                 } /* else { window.type != TYPE_OVERRIDE */
412
413                 fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n",
414                         window.window);
415                 fflush(stderr);
416
417                 XMapWindow(display, window.window);
418
419         } else /* if (own_window) { */
420 #endif
421                 /* root / desktop window */
422         {
423                 XWindowAttributes attrs;
424
425                 if (!window.window) {
426                         window.window = find_desktop_window(&window.root, &window.desktop);
427                 }
428
429                 if (XGetWindowAttributes(display, window.window, &attrs)) {
430                         window.width = attrs.width;
431                         window.height = attrs.height;
432                 }
433
434                 fprintf(stderr, PACKAGE_NAME": drawing to desktop window\n");
435         }
436
437         /* Drawable is same as window. This may be changed by double buffering. */
438         window.drawable = window.window;
439
440 #ifdef HAVE_XDBE
441         if (use_xdbe) {
442                 int major, minor;
443
444                 if (!XdbeQueryExtension(display, &major, &minor)) {
445                         use_xdbe = 0;
446                 } else {
447                         window.back_buffer = XdbeAllocateBackBufferName(display,
448                                 window.window, XdbeBackground);
449                         if (window.back_buffer != None) {
450                                 window.drawable = window.back_buffer;
451                                 fprintf(stderr, PACKAGE_NAME": drawing to double buffer\n");
452                         } else {
453                                 use_xdbe = 0;
454                         }
455                 }
456                 if (!use_xdbe) {
457                         ERR("failed to set up double buffer");
458                 }
459         }
460         if (!use_xdbe) {
461                 fprintf(stderr, PACKAGE_NAME": drawing to single buffer\n");
462         }
463 #endif
464         window.visual = DefaultVisual(display, DefaultScreen(display));
465         window.colourmap = DefaultColormap(display, DefaultScreen(display));
466 #ifdef IMLIB2
467         {
468                 cimlib_init(display, window.drawable, window.visual, window.colourmap);
469         }
470 #endif /* IMLIB2 */
471         XFlush(display);
472
473         /* set_transparent_background(window.window);
474          * must be done after double buffer stuff? */
475 #ifdef OWN_WINDOW
476         /* if (own_window) {
477                 set_transparent_background(window.window);
478                 XClearWindow(display, window.window);
479         } */
480 #endif
481
482         XSelectInput(display, window.window, ExposureMask | PropertyChangeMask
483 #ifdef OWN_WINDOW
484                 | (own_window ? (StructureNotifyMask |
485                 ButtonPressMask | ButtonReleaseMask) : 0)
486 #endif
487                 );
488 }
489
490 static Window find_subwindow(Window win, int w, int h)
491 {
492         unsigned int i, j;
493         Window troot, parent, *children;
494         unsigned int n;
495
496         /* search subwindows with same size as display or work area */
497
498         for (i = 0; i < 10; i++) {
499                 XQueryTree(display, win, &troot, &parent, &children, &n);
500
501                 for (j = 0; j < n; j++) {
502                         XWindowAttributes attrs;
503
504                         if (XGetWindowAttributes(display, children[j], &attrs)) {
505                                 /* Window must be mapped and same size as display or
506                                  * work space */
507                                 if (attrs.map_state != 0 && ((attrs.width == display_width
508                                                 && attrs.height == display_height)
509                                                 || (attrs.width == w && attrs.height == h))) {
510                                         win = children[j];
511                                         break;
512                                 }
513                         }
514                 }
515
516                 XFree(children);
517                 if (j == n) {
518                         break;
519                 }
520         }
521
522         return win;
523 }
524
525 long get_x11_color(const char *name)
526 {
527         XColor color;
528
529         color.pixel = 0;
530         if (!XParseColor(display, DefaultColormap(display, screen), name, &color)) {
531                 /* lets check if it's a hex colour with the # missing in front
532                  * if yes, then do something about it */
533                 char newname[DEFAULT_TEXT_BUFFER_SIZE];
534
535                 newname[0] = '#';
536                 strncpy(&newname[1], name, DEFAULT_TEXT_BUFFER_SIZE - 1);
537                 /* now lets try again */
538                 if (!XParseColor(display, DefaultColormap(display, screen), &newname[0],
539                                 &color)) {
540                         ERR("can't parse X color '%s'", name);
541                         return 0xFF00FF;
542                 }
543         }
544         if (!XAllocColor(display, DefaultColormap(display, screen), &color)) {
545                 ERR("can't allocate X color '%s'", name);
546         }
547
548         return (long) color.pixel;
549 }
550
551 void create_gc(void)
552 {
553         XGCValues values;
554
555         values.graphics_exposures = 0;
556         values.function = GXcopy;
557         window.gc = XCreateGC(display, window.drawable,
558                 GCFunction | GCGraphicsExposures, &values);
559 }
560
561 //Get current desktop number
562 static inline void get_x11_desktop_current(Display *current_display, Window root, Atom atom)
563 {
564         Atom actual_type;
565         int actual_format;
566         unsigned long nitems;
567         unsigned long bytes_after;
568         unsigned char *prop = NULL;
569         struct information *current_info = &info;
570
571         if ( (XGetWindowProperty( current_display, root, atom,
572                                   0, 1L, False, XA_CARDINAL,
573                                   &actual_type, &actual_format, &nitems,
574                                   &bytes_after, &prop ) == Success ) &&
575              (actual_type == XA_CARDINAL) &&
576              (nitems == 1L) && (actual_format == 32) ) {
577           current_info->x11.desktop.current = prop[0]+1;
578         }
579         if(prop) {
580           XFree(prop);
581         }
582 }
583
584 //Get total number of available desktops
585 static inline void get_x11_desktop_number(Display *current_display, Window root, Atom atom)
586 {
587         Atom actual_type;
588         int actual_format;
589         unsigned long nitems;
590         unsigned long bytes_after;
591         unsigned char *prop = NULL;
592         struct information *current_info = &info;
593
594         if ( (XGetWindowProperty( current_display, root, atom,
595                                   0, 1L, False, XA_CARDINAL,
596                                   &actual_type, &actual_format, &nitems,
597                                   &bytes_after, &prop ) == Success ) &&
598              (actual_type == XA_CARDINAL) &&
599              (nitems == 1L) && (actual_format == 32) ) {
600           current_info->x11.desktop.number = prop[0];
601         }
602         if(prop) {
603           XFree(prop);
604         }
605 }
606
607 //Get all desktop names
608 static inline void get_x11_desktop_names(Display *current_display, Window root, Atom atom)
609 {
610         Atom actual_type;
611         int actual_format;
612         unsigned long nitems;
613         unsigned long bytes_after;
614         unsigned char *prop = NULL;
615         struct information *current_info = &info;
616
617         if ( (XGetWindowProperty( current_display, root, atom,
618                                   0, (~0L), False, ATOM(UTF8_STRING),
619                                   &actual_type, &actual_format, &nitems,
620                                   &bytes_after, &prop ) == Success ) &&
621              (actual_type == ATOM(UTF8_STRING)) &&
622              (nitems > 0L) && (actual_format == 8) ) {
623
624           if(current_info->x11.desktop.all_names) {
625             free(current_info->x11.desktop.all_names);
626             current_info->x11.desktop.all_names = NULL;
627           }
628           current_info->x11.desktop.all_names = malloc(nitems*sizeof(char));
629           memcpy(current_info->x11.desktop.all_names, prop, nitems);
630           current_info->x11.desktop.nitems = nitems;
631         }
632         if(prop) {
633           XFree(prop);
634         }
635 }
636
637 //Get current desktop name
638 static inline void get_x11_desktop_current_name(char *names)
639 {
640         struct information *current_info = &info;
641         unsigned int i = 0, j = 0;
642         int k = 0;
643
644         while ( i < current_info->x11.desktop.nitems ) {
645           if ( names[i++] == '\0' ) {
646             if ( ++k == current_info->x11.desktop.current ) {
647               if (current_info->x11.desktop.name) {
648                 free(current_info->x11.desktop.name);
649                 current_info->x11.desktop.name = NULL;
650               }
651               current_info->x11.desktop.name = malloc((i-j)*sizeof(char));
652               //desktop names can be empty but should always be not null
653               strcpy( current_info->x11.desktop.name, (char *)&names[j] );
654               break;
655             }
656             j = i;
657           }
658         }
659 }
660
661 void get_x11_desktop_info(Display *current_display, Atom atom)
662 {
663         Window root;
664         static Atom atom_current, atom_number, atom_names;
665         struct information *current_info = &info;
666
667         root = RootWindow(current_display, current_info->x11.monitor.current);
668
669         //Check if we initialise else retrieve changed property
670         if (atom == 0) {
671           atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True);
672           atom_number  = XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True);
673           atom_names   = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True);
674           get_x11_desktop_current(current_display, root, atom_current);
675           get_x11_desktop_number(current_display, root, atom_number);
676           get_x11_desktop_names(current_display, root, atom_names);
677           get_x11_desktop_current_name(current_info->x11.desktop.all_names);
678         } else {
679           if (atom == atom_current) {
680             get_x11_desktop_current(current_display, root, atom_current);
681             get_x11_desktop_current_name(current_info->x11.desktop.all_names);
682           } else if (atom == atom_number) {
683             get_x11_desktop_number(current_display, root, atom_number);
684           } else if (atom == atom_names) {
685             get_x11_desktop_names(current_display, root, atom_names);
686             get_x11_desktop_current_name(current_info->x11.desktop.all_names);
687           }
688         }
689 }
690
691 void update_x11info(void)
692 {
693         struct information *current_info = &info;
694         current_info->x11.monitor.number = XScreenCount(display);
695         current_info->x11.monitor.current = XDefaultScreen(display);
696 }
697
698 #ifdef OWN_WINDOW
699 /* reserve window manager space */
700 void set_struts(int sidenum)
701 {
702         Atom strut;
703         if ((strut = ATOM(_NET_WM_STRUT)) != None) {
704                 /* reserve space at left, right, top, bottom */
705                 signed long sizes[12] = {0};
706                 int i;
707
708                 /* define strut depth */
709                 switch (sidenum) {
710                         case 0:
711                         {
712                                 /* left side */
713                                 sizes[0] = window.x + window.width;
714                                 break;
715                         }
716                         case 1:
717                         {
718                                 /* right side */
719                                 sizes[1] = display_width - window.x;
720                                 break;
721                         }
722                         case 2:
723                         {
724                                 /* top side */
725                                 sizes[2] = window.y + window.height;
726                                 break;
727                         }
728                         case 3:
729                         {
730                                 /* bottom side */
731                                 sizes[3] = display_height - window.y;
732                                 break;
733                         }
734                 }
735
736                 /* define partial strut length */
737                 if (sidenum <= 1) {
738                         sizes[4 + (sidenum*2)] = window.y;
739                         sizes[5 + (sidenum*2)] = window.y + window.height;
740                 } else if (sidenum <= 3) {
741                         sizes[4 + (sidenum*2)] = window.x;
742                         sizes[5 + (sidenum*2)] = window.x + window.width;
743                 }
744
745                 /* check constraints */
746                 for (i = 0; i < 12; i++) {
747                         if (sizes[i] < 0) {
748                                 sizes[i] = 0;
749                         } else {
750                                 if (i <= 1 || i >= 8) {
751                                         if (sizes[i] > display_width) {
752                                                 sizes[i] = display_width;
753                                         }
754                                 } else {
755                                         if (sizes[i] > display_height) {
756                                                 sizes[i] = display_height;
757                                         }
758                                 }
759                         }
760                 }
761
762                 XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
763                                 PropModeReplace, (unsigned char *) &sizes, 4);
764
765                 if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) {
766                         XChangeProperty(display, window.window, strut, XA_CARDINAL, 32,
767                                         PropModeReplace, (unsigned char *) &sizes, 12);
768                 }
769         }
770 }
771 #endif /* OWN_WINDOW */