2 * Conky, a system monitor, based on torsmo
4 * This program is licensed under BSD license, read COPYING
13 #include <X11/Xatom.h>
14 #include <X11/Xutil.h>
16 #include <X11/Xft/Xft.h>
27 /* some basic X11 stuff */
32 static int set_transparent;
33 static int background_colour;
35 /* workarea from _NET_WORKAREA, this is where window / text is aligned */
39 struct conky_window window;
41 /* local prototypes */
42 static void update_workarea();
43 static Window find_window_to_draw();
44 static Window find_subwindow(Window win, int w, int h);
49 if ((display = XOpenDisplay(0)) == NULL)
50 CRIT_ERR("can't open display: %s", XDisplayName(0));
52 screen = DefaultScreen(display);
53 display_width = DisplayWidth(display, screen);
54 display_height = DisplayHeight(display, screen);
59 static void update_workarea()
61 Window root = RootWindow(display, screen);
62 unsigned long nitems, bytes;
63 unsigned char *buf = NULL;
67 /* default work area is display */
70 workarea[2] = display_width;
71 workarea[3] = display_height;
73 /* get current desktop */
74 if (XGetWindowProperty(display, root, ATOM(_NET_CURRENT_DESKTOP),
75 0, 1, False, XA_CARDINAL, &type, &format,
76 &nitems, &bytes, &buf) == Success
77 && type == XA_CARDINAL && nitems > 0) {
80 /* long desktop = * (long *) buf; */
93 static Window find_window_to_draw()
97 unsigned long nitems, bytes;
99 Window root = RootWindow(display, screen);
101 Window troot, parent, *children;
102 unsigned char *buf = NULL;
104 /* some window managers set __SWM_VROOT to some child of root window */
106 XQueryTree(display, root, &troot, &parent, &children, &n);
107 for (i = 0; i < (int) n; i++) {
108 if (XGetWindowProperty
109 (display, children[i], ATOM(__SWM_VROOT), 0, 1, False,
110 XA_WINDOW, &type, &format, &nitems, &bytes,
111 &buf) == Success && type == XA_WINDOW) {
112 win = *(Window *) buf;
116 "Conky: drawing to window from __SWM_VROOT property\n");
127 /* get subwindows from root */
128 win = find_subwindow(root, -1, -1);
132 win = find_subwindow(win, workarea[2], workarea[3]);
141 "Conky: drawing to subwindow of root window (%lx)\n",
144 fprintf(stderr, "Conky: drawing to root window\n");
149 /* sets background to ParentRelative for the Window and all parents */
150 inline void set_transparent_background(Window win)
152 static int colour_set = -1;
153 if (set_transparent) {
156 for (i = 0; i < 50 && parent != RootWindow(display, screen); i++) {
160 XSetWindowBackgroundPixmap(display, parent, ParentRelative);
162 XQueryTree(display, parent, &r, &parent, &children, &n);
165 } else if (colour_set != background_colour) {
166 XSetWindowBackground(display, win, background_colour);
167 colour_set = background_colour;
169 //XClearWindow(display, win); not sure why this was here
172 #if defined OWN_WINDOW
173 void init_window(int own_window, int w, int h, int l, int fixed_pos, int set_trans, int back_colour)
175 void init_window(int own_window, int w, int h, int l, int set_trans, int back_colour)
178 /* There seems to be some problems with setting transparent background (on
179 * fluxbox this time). It doesn't happen always and I don't know why it
180 * happens but I bet the bug is somewhere here. */
181 set_transparent = set_trans;
182 background_colour = back_colour;
186 /* looks like root pixmap isn't needed for anything */
188 XSetWindowAttributes attrs;
189 XClassHint class_hints;
192 attrs.background_pixel = get_x11_color("green");
195 window.window = XCreateWindow(display, RootWindow(display, screen), window.x, window.y, w, h, 0, CopyFromParent, /* depth */
196 CopyFromParent, /* class */
197 CopyFromParent, /* visual */
198 CWBackPixel, &attrs);
200 class_hints.res_class = "conky";
201 class_hints.res_name = "conky";
202 XSetClassHint(display, window.window,
205 /*set_transparent_background(window.window);*/
207 XStoreName(display, window.window, "conky");
209 XClearWindow(display, window.window);
212 XMoveWindow(display, window.window, window.x,
217 /* turn off decorations */
219 XInternAtom(display, "_MOTIF_WM_HINTS", True);
221 long prop[5] = { 2, 0, 0, 0, 0 };
222 XChangeProperty(display, window.window, a,
223 a, 32, PropModeReplace,
224 (unsigned char *) prop, 5);
227 /* set window sticky (to all desktops) */
228 a = XInternAtom(display, "_NET_WM_DESKTOP", True);
230 long prop = 0xFFFFFFFF;
231 XChangeProperty(display, window.window, a,
234 (unsigned char *) &prop,
238 /* make sure the layer is on the bottom */
239 a = XInternAtom(display, "_WIN_LAYER", True);
242 XChangeProperty(display, window.window, a,
245 (unsigned char *) &prop, 1);
250 XMapWindow(display, window.window);
253 /* root / desktop window */
255 XWindowAttributes attrs;
258 window.window = find_window_to_draw();
260 if (XGetWindowAttributes(display, window.window, &attrs)) {
261 window.width = attrs.width;
262 window.height = attrs.height;
266 /* Drawable is same as window. This may be changed by double buffering. */
267 window.drawable = window.window;
272 if (!XdbeQueryExtension(display, &major, &minor)) {
276 XdbeAllocateBackBufferName(display,
279 if (window.back_buffer != None) {
280 window.drawable = window.back_buffer;
282 "Conky: drawing to double buffer\n");
287 ERR("failed to set up double buffer");
290 fprintf(stderr, "Conky: drawing to single buffer\n");
295 /*set_transparent_background(window.window); must be done after double buffer stuff? */
298 set_transparent_background(window.window);
299 XClearWindow(display, window.window);
303 XSelectInput(display, window.window, ExposureMask
306 ? (StructureNotifyMask | PropertyChangeMask) : 0)
311 static Window find_subwindow(Window win, int w, int h)
314 Window troot, parent, *children;
317 /* search subwindows with same size as display or work area */
319 for (i = 0; i < 10; i++) {
320 XQueryTree(display, win, &troot, &parent, &children, &n);
322 for (j = 0; j < n; j++) {
323 XWindowAttributes attrs;
325 if (XGetWindowAttributes
326 (display, children[j], &attrs)) {
327 /* Window must be mapped and same size as display or work space */
328 if (attrs.map_state != 0 &&
329 ((attrs.width == display_width
330 && attrs.height == display_height)
332 && attrs.height == h))) {
347 long get_x11_color(const char *name)
352 (display, DefaultColormap(display, screen), name, &color)) {
353 ERR("can't parse X color '%s'", name);
357 (display, DefaultColormap(display, screen), &color))
358 ERR("can't allocate X color '%s'", name);
360 return (long) color.pixel;
366 values.graphics_exposures = 0;
367 values.function = GXcopy;
368 window.gc = XCreateGC(display, window.drawable,
369 GCFunction | GCGraphicsExposures, &values);