X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fx11.c;h=e933a64cc78bb63d8f3049b238b96099d5ee04a0;hb=fc1bd4cf0a46eb594789d5a5f72a7f9427e89431;hp=24f1d5f8947443cc6a60a1ddf015eec245a45be8;hpb=49c9b8d6d5ca6105656aec355d085ba6cd24fe23;p=monky diff --git a/src/x11.c b/src/x11.c index 24f1d5f..e933a64 100644 --- a/src/x11.c +++ b/src/x11.c @@ -1,37 +1,64 @@ -/* +/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=c + * * Conky, a system monitor, based on torsmo * - * This program is licensed under BSD license, read COPYING + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * - * $Id$ */ - +#include "config.h" #include "conky.h" +#include "logging.h" +#include "common.h" -#ifdef X11 +#include "x11.h" #include #include #include #include +#ifdef IMLIB2 +#include "imlib2.h" +#endif /* IMLIB2 */ + #ifdef XFT #include +int use_xft; #endif -#include - -#ifdef XDBE +#ifdef HAVE_XDBE int use_xdbe; #endif -#ifdef XFT -int use_xft = 0; -#endif - -#define WINDOW_NAME_FMT "%s - conky" +#ifdef USE_ARGB +int use_argb_visual; +int have_argb_visual; +#endif /* USE_ARGB */ +int own_window_argb_value; /* some basic X11 stuff */ -Display *display; +Display *display = NULL; int display_width; int display_height; int screen; @@ -43,61 +70,44 @@ int workarea[4]; /* Window stuff */ struct conky_window window; +char window_created = 0; /* local prototypes */ -static void update_workarea(); +static void update_workarea(void); static Window find_desktop_window(Window *p_root, Window *p_desktop); static Window find_subwindow(Window win, int w, int h); /* X11 initializer */ -void init_X11() +void init_X11(const char *disp) { - if ((display = XOpenDisplay(0)) == NULL) - CRIT_ERR("can't open display: %s", XDisplayName(0)); + if (!display) { + if ((display = XOpenDisplay(disp)) == NULL) { + CRIT_ERR(NULL, NULL, "can't open display: %s", XDisplayName(disp)); + } + } screen = DefaultScreen(display); display_width = DisplayWidth(display, screen); display_height = DisplayHeight(display, screen); + get_x11_desktop_info(display, 0); + update_workarea(); } -static void update_workarea() +static void update_workarea(void) { - Window root = RootWindow(display, screen); - unsigned long nitems, bytes; - unsigned char *buf = NULL; - Atom type; - int format; - /* default work area is display */ workarea[0] = 0; workarea[1] = 0; workarea[2] = display_width; workarea[3] = display_height; - - /* get current desktop */ - if (XGetWindowProperty(display, root, ATOM(_NET_CURRENT_DESKTOP), - 0, 1, False, XA_CARDINAL, &type, &format, - &nitems, &bytes, &buf) == Success - && type == XA_CARDINAL && nitems > 0) { - - //Currently unused - /* long desktop = * (long *) buf; */ - - XFree(buf); - buf = 0; - - } - - if (buf) { - XFree(buf); - buf = 0; - } } -/* Find root window and desktop window. Return desktop window on success, - * and set root and desktop byref return values. Return 0 on failure. */ +/* Find root window and desktop window. + * Return desktop window on success, + * and set root and desktop byref return values. + * Return 0 on failure. */ static Window find_desktop_window(Window *p_root, Window *p_desktop) { Atom type; @@ -109,25 +119,26 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) Window troot, parent, *children; unsigned char *buf = NULL; - if (!p_root || !p_desktop) - return(0); + if (!p_root || !p_desktop) { + return 0; + } /* some window managers set __SWM_VROOT to some child of root window */ XQueryTree(display, root, &troot, &parent, &children, &n); for (i = 0; i < (int) n; i++) { - if (XGetWindowProperty - (display, children[i], ATOM(__SWM_VROOT), 0, 1, False, - XA_WINDOW, &type, &format, &nitems, &bytes, - &buf) == Success && type == XA_WINDOW) { + if (XGetWindowProperty(display, children[i], ATOM(__SWM_VROOT), 0, 1, + False, XA_WINDOW, &type, &format, &nitems, &bytes, &buf) + == Success && type == XA_WINDOW) { win = *(Window *) buf; XFree(buf); XFree(children); fprintf(stderr, - "Conky: desktop window (%lx) found from __SWM_VROOT property\n", win); + PACKAGE_NAME": desktop window (%lx) found from __SWM_VROOT property\n", + win); fflush(stderr); - *p_root=win; - *p_desktop=win; + *p_root = win; + *p_desktop = win; return win; } @@ -150,314 +161,434 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) buf = 0; } - if (win != root) + if (win != root) { fprintf(stderr, - "Conky: desktop window (%lx) is subwindow of root window (%lx)\n",win,root); - else - fprintf(stderr, "Conky: desktop window (%lx) is root window\n",win); + PACKAGE_NAME": desktop window (%lx) is subwindow of root window (%lx)\n", + win, root); + } else { + fprintf(stderr, PACKAGE_NAME": desktop window (%lx) is root window\n", win); + } fflush(stderr); - *p_root=root; - *p_desktop=win; + *p_root = root; + *p_desktop = win; return win; } -/* sets background to ParentRelative for the Window and all parents */ -inline void set_transparent_background(Window win) +static int colour_set = -1; +/* if no argb visual is configured sets background to ParentRelative for the Window and all parents, + else real transparency is used */ +void set_transparent_background(Window win, int alpha) { - static int colour_set = -1; + (void)alpha; /* disable warnings when unused */ + +#ifdef USE_ARGB + if (have_argb_visual) { + // real transparency + if (set_transparent) { + XSetWindowBackground(display, win, 0x00); + } else if (colour_set != background_colour) { + XSetWindowBackground(display, win, + background_colour | (alpha << 24)); + colour_set = background_colour; + } + } else { +#endif /* USE_ARGB */ + // pseudo transparency + if (set_transparent) { Window parent = win; unsigned int i; + for (i = 0; i < 50 && parent != RootWindow(display, screen); i++) { Window r, *children; unsigned int n; - + XSetWindowBackgroundPixmap(display, parent, ParentRelative); - + XQueryTree(display, parent, &r, &parent, &children, &n); XFree(children); - } + } } else if (colour_set != background_colour) { XSetWindowBackground(display, win, background_colour); colour_set = background_colour; + } +#ifdef USE_ARGB + } +#endif /* USE_ARGB */ } - //XClearWindow(display, win); not sure why this was here + +#ifdef USE_ARGB +static int get_argb_visual(Visual** visual, int *depth) { + /* code from gtk project, gdk_screen_get_rgba_visual */ + XVisualInfo visual_template; + XVisualInfo *visual_list; + int nxvisuals = 0, i; + + visual_template.screen = screen; + visual_list = XGetVisualInfo (display, VisualScreenMask, + &visual_template, &nxvisuals); + for (i = 0; i < nxvisuals; i++) { + if (visual_list[i].depth == 32 && + (visual_list[i].red_mask == 0xff0000 && + visual_list[i].green_mask == 0x00ff00 && + visual_list[i].blue_mask == 0x0000ff)) { + *visual = visual_list[i].visual; + *depth = visual_list[i].depth; + DBGP("Found ARGB Visual"); + XFree(visual_list); + return 1; + } + } + // no argb visual available + DBGP("No ARGB Visual found"); + XFree(visual_list); + return 0; } +#endif /* USE_ARGB */ -void init_window(int own_window, int w, int h, int set_trans, int back_colour, char * nodename, - char **argv, int argc) +void destroy_window(void) { - /* There seems to be some problems with setting transparent background (on - * fluxbox this time). It doesn't happen always and I don't know why it +#ifdef XFT + if(window.xftdraw) { + XftDrawDestroy(window.xftdraw); + } +#endif + if(window.gc) { + XFreeGC(display, window.gc); + } + if(window.gc_back) { + XFreeGC(display, window.gc_back); + } + if(window.back_buffer != None) { + XFreePixmap(display, window.back_buffer); + } + memset(&window, 0, sizeof(struct conky_window)); + colour_set = -1; +} + +void init_window(int own_window, int w, int h, int set_trans, int back_colour, + char **argv, int argc) +{ + /* There seems to be some problems with setting transparent background + * (on fluxbox this time). It doesn't happen always and I don't know why it * happens but I bet the bug is somewhere here. */ set_transparent = set_trans; background_colour = back_colour; - - nodename = (char *)nodename; + window_created = 1; #ifdef OWN_WINDOW if (own_window) { - { - /* Allow WM control of conky again. Shielding conky from the WM - * via override redirect creates more problems than it's worth and - * makes it impossible to use tools like devilspie to manage the - * conky windows beyond the parameters we offer. ButtonPress - * events are now explicitly forwarded to the desktop window. */ - XSetWindowAttributes attrs = { - ParentRelative,0L,0,0L,0,0,Always,0L,0L,False, - StructureNotifyMask|ExposureMask|ButtonPressMask|ButtonReleaseMask, - 0L,False,0,0 }; + int depth = 0, flags; + Visual *visual = NULL; + + if (!find_desktop_window(&window.root, &window.desktop)) { + return; + } + +#ifdef USE_ARGB + if (use_argb_visual && get_argb_visual(&visual, &depth)) { + have_argb_visual = 1; + window.visual = visual; + window.colourmap = XCreateColormap(display, + DefaultRootWindow(display), window.visual, AllocNone); + } else { +#endif /* USE_ARGB */ + window.visual = DefaultVisual(display, screen); + window.colourmap = DefaultColormap(display, screen); + depth = CopyFromParent; + visual = CopyFromParent; +#ifdef USE_ARGB + } +#endif /* USE_ARGB */ + + if (window.type == TYPE_OVERRIDE) { + + /* An override_redirect True window. + * No WM hints or button processing needed. */ + XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, + Always, 0L, 0L, False, StructureNotifyMask | ExposureMask, 0L, + True, 0, 0 }; +#ifdef USE_ARGB + if (have_argb_visual) { + attrs.colormap = window.colourmap; + flags = CWBorderPixel | CWColormap | CWOverrideRedirect; + } else { +#endif /* USE_ARGB */ + flags = CWBackPixel | CWOverrideRedirect; +#ifdef USE_ARGB + } +#endif /* USE_ARGB */ + + /* Parent is desktop window (which might be a child of root) */ + window.window = XCreateWindow(display, window.desktop, window.x, + window.y, w, h, 0, depth, InputOutput, visual, + flags, &attrs); + + XLowerWindow(display, window.window); + + fprintf(stderr, PACKAGE_NAME": window type - override\n"); + fflush(stderr); + } else { /* window.type != TYPE_OVERRIDE */ + + /* A window managed by the window manager. + * Process hints and buttons. */ + XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, + Always, 0L, 0L, False, StructureNotifyMask | ExposureMask | + ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 }; XClassHint classHint; XWMHints wmHint; Atom xa; - char window_title[256]; - - /* We want to parent the window to the root so it's under WM control, - * but we want to forward button clicks to the desktop window for menus. - * On some desktop systems, the desktop window != root window. */ - if ( !find_desktop_window( &window.root, &window.desktop ) ) - return; - - window.window = XCreateWindow(display, window.root, - window.x, window.y, w, h, 0, - CopyFromParent, - InputOutput, - CopyFromParent, - CWBackPixel|CWOverrideRedirect, - &attrs); - - fprintf(stderr, "Conky: drawing to created window (%lx)\n", window.window); - fflush(stderr); - classHint.res_name = window.wm_class_name; +#ifdef USE_ARGB + if (have_argb_visual) { + attrs.colormap = window.colourmap; + flags = CWBorderPixel | CWColormap | CWOverrideRedirect; + } else { +#endif /* USE_ARGB */ + flags = CWBackPixel | CWOverrideRedirect; +#ifdef USE_ARGB + } +#endif /* USE_ARGB */ + + if (window.type == TYPE_DOCK) { + window.x = window.y = 0; + } + /* Parent is root window so WM can take control */ + + fprintf(stderr, PACKAGE_NAME": creating window of %d x %d x %d\n",w,h,depth); + window.window = XCreateWindow(display, window.root, window.x, + window.y, w, h, 0, depth, InputOutput, visual, + flags, &attrs); + + classHint.res_name = window.class_name; classHint.res_class = classHint.res_name; wmHint.flags = InputHint | StateHint; - wmHint.input = False; - wmHint.initial_state = NormalState; - - sprintf(window_title,WINDOW_NAME_FMT,nodename); + /* allow decorated windows to be given input focus by WM */ + wmHint.input = + TEST_HINT(window.hints, HINT_UNDECORATED) ? False : True; + if (window.type == TYPE_DOCK || window.type == TYPE_PANEL) { + wmHint.initial_state = WithdrawnState; + } else { + wmHint.initial_state = NormalState; + } - XmbSetWMProperties (display, window.window, window_title, NULL, - argv, argc, - NULL, &wmHint, &classHint); + XmbSetWMProperties(display, window.window, NULL, NULL, argv, + argc, NULL, &wmHint, &classHint); + XStoreName(display, window.window, window.title); /* Sets an empty WM_PROTOCOLS property */ - XSetWMProtocols(display,window.window,NULL,0); - + XSetWMProtocols(display, window.window, NULL, 0); /* Set window type */ - if ( (xa = ATOM(_NET_WM_WINDOW_TYPE)) != None ) - { + if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) { Atom prop; - switch(window.type) { - case TYPE_DESKTOP: - { - prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); - fprintf(stderr, "Conky: window type - desktop\n"); fflush(stderr); - } - break; - - case TYPE_NORMAL: - default: - { - prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); - fprintf(stderr, "Conky: window type - normal\n"); fflush(stderr); - } - break; + + switch (window.type) { + case TYPE_DESKTOP: + prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); + fprintf(stderr, PACKAGE_NAME": window type - desktop\n"); + fflush(stderr); + break; + case TYPE_DOCK: + prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); + fprintf(stderr, PACKAGE_NAME": window type - dock\n"); + fflush(stderr); + break; + case TYPE_PANEL: + prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); + fprintf(stderr, PACKAGE_NAME": window type - panel\n"); + fflush(stderr); + break; + case TYPE_NORMAL: + default: + prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); + fprintf(stderr, PACKAGE_NAME": window type - normal\n"); + fflush(stderr); + break; } - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeReplace, - (unsigned char *) &prop, 1); + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeReplace, (unsigned char *) &prop, 1); } /* Set desired hints */ - + /* Window decorations */ - if (TEST_HINT(window.hints,HINT_UNDECORATED)) { - fprintf(stderr, "Conky: hint - undecorated\n"); fflush(stderr); - - xa = ATOM(_MOTIF_WM_HINTS); - if (xa != None) { - long prop[5] = { 2, 0, 0, 0, 0 }; - XChangeProperty(display, window.window, xa, - xa, 32, PropModeReplace, - (unsigned char *) prop, 5); - } + if (TEST_HINT(window.hints, HINT_UNDECORATED)) { + /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n"); + fflush(stderr); */ + + xa = ATOM(_MOTIF_WM_HINTS); + if (xa != None) { + long prop[5] = { 2, 0, 0, 0, 0 }; + XChangeProperty(display, window.window, xa, xa, 32, + PropModeReplace, (unsigned char *) prop, 5); + } } /* Below other windows */ - if (TEST_HINT(window.hints,HINT_BELOW)) { - fprintf(stderr, "Conky: hint - below\n"); fflush(stderr); - - xa = ATOM(_WIN_LAYER); - if (xa != None) { - long prop = 0; - XChangeProperty(display, window.window, xa, - XA_CARDINAL, 32, - PropModeAppend, - (unsigned char *) &prop, 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } + if (TEST_HINT(window.hints, HINT_BELOW)) { + /* fprintf(stderr, PACKAGE_NAME": hint - below\n"); + fflush(stderr); */ + + xa = ATOM(_WIN_LAYER); + if (xa != None) { + long prop = 0; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, (unsigned char *) &prop, 1); + } + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } } /* Above other windows */ - if (TEST_HINT(window.hints,HINT_ABOVE)) { - fprintf(stderr, "Conky: hint - above\n"); fflush(stderr); - - xa = ATOM(_WIN_LAYER); - if (xa != None) { - long prop = 6; - XChangeProperty(display, window.window, xa, - XA_CARDINAL, 32, - PropModeAppend, - (unsigned char *) &prop, 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } - } + if (TEST_HINT(window.hints, HINT_ABOVE)) { + /* fprintf(stderr, PACKAGE_NAME": hint - above\n"); + fflush(stderr); */ + + xa = ATOM(_WIN_LAYER); + if (xa != None) { + long prop = 6; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, (unsigned char *) &prop, 1); + } + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } + } /* Sticky */ - if (TEST_HINT(window.hints,HINT_STICKY)) { - fprintf(stderr, "Conky: hint - sticky\n"); fflush(stderr); - - xa = ATOM(_NET_WM_DESKTOP); - if (xa != None) { - CARD32 xa_prop = 0xFFFFFFFF; - XChangeProperty(display, window.window, xa, - XA_CARDINAL, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } - } + if (TEST_HINT(window.hints, HINT_STICKY)) { + /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n"); + fflush(stderr); */ + + xa = ATOM(_NET_WM_DESKTOP); + if (xa != None) { + CARD32 xa_prop = 0xFFFFFFFF; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } + } /* Skip taskbar */ - if (TEST_HINT(window.hints,HINT_SKIP_TASKBAR)) { - fprintf(stderr, "Conky: hint - skip_taskbar\n"); fflush(stderr); - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } - } + if (TEST_HINT(window.hints, HINT_SKIP_TASKBAR)) { + /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n"); + fflush(stderr); */ + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } + } /* Skip pager */ - if (TEST_HINT(window.hints,HINT_SKIP_PAGER)) { - fprintf(stderr, "Conky: hint - skip_pager\n"); fflush(stderr); - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER); - XChangeProperty(display, window.window, xa, - XA_ATOM, 32, - PropModeAppend, - (unsigned char *) &xa_prop, - 1); - } - } - - XMapWindow(display, window.window); + if (TEST_HINT(window.hints, HINT_FULLSCREEN)) { + fprintf(stderr, PACKAGE_NAME": hint - fullscreen\n"); + fflush(stderr); + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_FULLSCREEN); + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &xa_prop, 1); + } + } } + + fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n", + window.window); + fflush(stderr); + + XMapWindow(display, window.window); + } else -#endif - /* root / desktop window */ +#endif /* OWN_WINDOW */ { - XWindowAttributes attrs; + if (!window.window) { + window.window = find_desktop_window(&window.root, &window.desktop); + } + window.visual = DefaultVisual(display, screen); + window.colourmap = DefaultColormap(display, screen); - if (!window.window) - window.window = find_desktop_window( &window.root, &window.desktop ); + fprintf(stderr, PACKAGE_NAME": drawing to desktop window\n"); + } + { + fprintf(stderr, PACKAGE_NAME": getting window attrs\n"); + XWindowAttributes attrs; if (XGetWindowAttributes(display, window.window, &attrs)) { window.width = attrs.width; window.height = attrs.height; + window.depth = attrs.depth; } - - fprintf(stderr, "Conky: drawing to desktop window\n"); } /* Drawable is same as window. This may be changed by double buffering. */ window.drawable = window.window; -#ifdef XDBE +#ifdef HAVE_XDBE if (use_xdbe) { - int major, minor; - if (!XdbeQueryExtension(display, &major, &minor)) { - use_xdbe = 0; - } else { - window.back_buffer = - XdbeAllocateBackBufferName(display, - window.window, - XdbeBackground); + { + window.back_buffer = XCreatePixmap(display, window.window, + window.width, window.height, window.depth); if (window.back_buffer != None) { window.drawable = window.back_buffer; - fprintf(stderr, - "Conky: drawing to double buffer\n"); - } else + fprintf(stderr, PACKAGE_NAME": created %d x %d x %d back buffer\n",window.width, window.height, window.depth); + } else { use_xdbe = 0; + } + } + if (!use_xdbe) { + NORM_ERR("failed to set up double buffer"); } - if (!use_xdbe) - ERR("failed to set up double buffer"); } - if (!use_xdbe) - fprintf(stderr, "Conky: drawing to single buffer\n"); + if (!use_xdbe) { + fprintf(stderr, PACKAGE_NAME": drawing to single buffer\n"); + } #endif - +#ifdef IMLIB2 + { + cimlib_init(display, window.drawable, window.visual, window.colourmap); + } +#endif /* IMLIB2 */ XFlush(display); - /*set_transparent_background(window.window); must be done after double buffer stuff? */ -#ifdef OWN_WINDOW - /*if (own_window) { - set_transparent_background(window.window); - XClearWindow(display, window.window); -}*/ -#endif - - XSelectInput(display, window.window, ExposureMask + XSelectInput(display, window.window, ExposureMask | PropertyChangeMask #ifdef OWN_WINDOW - | (own_window - ? (StructureNotifyMask | PropertyChangeMask | - ButtonPressMask | ButtonReleaseMask) : 0) + | (own_window ? (StructureNotifyMask | + ButtonPressMask | ButtonReleaseMask) : 0) #endif - ); + ); } static Window find_subwindow(Window win, int w, int h) @@ -474,14 +605,12 @@ static Window find_subwindow(Window win, int w, int h) for (j = 0; j < n; j++) { XWindowAttributes attrs; - if (XGetWindowAttributes - (display, children[j], &attrs)) { - /* Window must be mapped and same size as display or work space */ - if (attrs.map_state != 0 && - ((attrs.width == display_width - && attrs.height == display_height) - || (attrs.width == w - && attrs.height == h))) { + if (XGetWindowAttributes(display, children[j], &attrs)) { + /* Window must be mapped and same size as display or + * work space */ + if (attrs.map_state != 0 && ((attrs.width == display_width + && attrs.height == display_height) + || (attrs.width == w && attrs.height == h))) { win = children[j]; break; } @@ -489,45 +618,264 @@ static Window find_subwindow(Window win, int w, int h) } XFree(children); - if (j == n) + if (j == n) { break; + } } return win; } -long get_x11_color(const char *name) +void create_gc(void) +{ + XGCValues values; + + values.graphics_exposures = 0; + values.function = GXcopy; + window.gc = XCreateGC(display, window.drawable, + GCFunction | GCGraphicsExposures, &values); + window.gc_back = XCreateGC(display, window.drawable, + GCFunction | GCGraphicsExposures, &values); +} + +//Get current desktop number +static inline void get_x11_desktop_current(Display *current_display, Window root, Atom atom) { - XColor color; - color.pixel = 0; - if (!XParseColor - (display, DefaultColormap(display, screen), name, &color)) { - /* lets check if it's a hex colour with the # missing in front - * if yes, then do something about it - */ - char newname[64]; - newname[0] = '#'; - strncpy(&newname[1], name, 62); - /* now lets try again */ - if (!XParseColor(display, DefaultColormap(display, screen), &newname[0], &color)) { - ERR("can't parse X color '%s'", name); - return 0xFF00FF; + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = NULL; + struct information *current_info = &info; + + if (atom == None) return; + + if ( (XGetWindowProperty( current_display, root, atom, + 0, 1L, False, XA_CARDINAL, + &actual_type, &actual_format, &nitems, + &bytes_after, &prop ) == Success ) && + (actual_type == XA_CARDINAL) && + (nitems == 1L) && (actual_format == 32) ) { + current_info->x11.desktop.current = prop[0]+1; + } + if(prop) { + XFree(prop); + } +} + +//Get total number of available desktops +static inline void get_x11_desktop_number(Display *current_display, Window root, Atom atom) +{ + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = NULL; + struct information *current_info = &info; + + if (atom == None) return; + + if ( (XGetWindowProperty( current_display, root, atom, + 0, 1L, False, XA_CARDINAL, + &actual_type, &actual_format, &nitems, + &bytes_after, &prop ) == Success ) && + (actual_type == XA_CARDINAL) && + (nitems == 1L) && (actual_format == 32) ) { + current_info->x11.desktop.number = prop[0]; + } + if(prop) { + XFree(prop); + } +} + +//Get all desktop names +static inline void get_x11_desktop_names(Display *current_display, Window root, Atom atom) +{ + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = NULL; + struct information *current_info = &info; + + if (atom == None) return; + + if ( (XGetWindowProperty( current_display, root, atom, + 0, (~0L), False, ATOM(UTF8_STRING), + &actual_type, &actual_format, &nitems, + &bytes_after, &prop ) == Success ) && + (actual_type == ATOM(UTF8_STRING)) && + (nitems > 0L) && (actual_format == 8) ) { + + if(current_info->x11.desktop.all_names) { + free(current_info->x11.desktop.all_names); + current_info->x11.desktop.all_names = NULL; } + current_info->x11.desktop.all_names = malloc(nitems*sizeof(char)); + memcpy(current_info->x11.desktop.all_names, prop, nitems); + current_info->x11.desktop.nitems = nitems; + } + if(prop) { + XFree(prop); } - if (!XAllocColor - (display, DefaultColormap(display, screen), &color)) - ERR("can't allocate X color '%s'", name); +} - return (long) color.pixel; +//Get current desktop name +static inline void get_x11_desktop_current_name(char *names) +{ + struct information *current_info = &info; + unsigned int i = 0, j = 0; + int k = 0; + + while ( i < current_info->x11.desktop.nitems ) { + if ( names[i++] == '\0' ) { + if ( ++k == current_info->x11.desktop.current ) { + if (current_info->x11.desktop.name) { + free(current_info->x11.desktop.name); + current_info->x11.desktop.name = NULL; + } + current_info->x11.desktop.name = malloc((i-j)*sizeof(char)); + //desktop names can be empty but should always be not null + strcpy( current_info->x11.desktop.name, (char *)&names[j] ); + break; + } + j = i; + } + } } -void create_gc() +void get_x11_desktop_info(Display *current_display, Atom atom) { - XGCValues values; - values.graphics_exposures = 0; - values.function = GXcopy; - window.gc = XCreateGC(display, window.drawable, - GCFunction | GCGraphicsExposures, &values); + Window root; + static Atom atom_current, atom_number, atom_names; + struct information *current_info = &info; + XWindowAttributes window_attributes; + + root = RootWindow(current_display, current_info->x11.monitor.current); + + /* Check if we initialise else retrieve changed property */ + if (atom == 0) { + atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True); + atom_number = XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True); + atom_names = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True); + get_x11_desktop_current(current_display, root, atom_current); + get_x11_desktop_number(current_display, root, atom_number); + get_x11_desktop_names(current_display, root, atom_names); + get_x11_desktop_current_name(current_info->x11.desktop.all_names); + + /* Set the PropertyChangeMask on the root window, if not set */ + XGetWindowAttributes(display, root, &window_attributes); + if (!(window_attributes.your_event_mask & PropertyChangeMask)) { + XSetWindowAttributes attributes; + attributes.event_mask = window_attributes.your_event_mask | PropertyChangeMask; + XChangeWindowAttributes(display, root, CWEventMask, &attributes); + XGetWindowAttributes(display, root, &window_attributes); + } + } else { + if (atom == atom_current) { + get_x11_desktop_current(current_display, root, atom_current); + get_x11_desktop_current_name(current_info->x11.desktop.all_names); + } else if (atom == atom_number) { + get_x11_desktop_number(current_display, root, atom_number); + } else if (atom == atom_names) { + get_x11_desktop_names(current_display, root, atom_names); + get_x11_desktop_current_name(current_info->x11.desktop.all_names); + } + } +} + +int update_x11info(void) +{ + struct information *current_info = &info; + if (x_initialised != YES) + return 0; + current_info->x11.monitor.number = XScreenCount(display); + current_info->x11.monitor.current = XDefaultScreen(display); + return 0; +} + +#ifdef OWN_WINDOW +/* reserve window manager space */ +void set_struts(int sidenum) +{ + Atom strut; + if ((strut = ATOM(_NET_WM_STRUT)) != None) { + /* reserve space at left, right, top, bottom */ + signed long sizes[12] = {0}; + int i; + + /* define strut depth */ + switch (sidenum) { + case 0: + /* left side */ + sizes[0] = window.x + window.width; + break; + case 1: + /* right side */ + sizes[1] = display_width - window.x; + break; + case 2: + /* top side */ + sizes[2] = window.y + window.height; + break; + case 3: + /* bottom side */ + sizes[3] = display_height - window.y; + break; + } + + /* define partial strut length */ + if (sidenum <= 1) { + sizes[4 + (sidenum*2)] = window.y; + sizes[5 + (sidenum*2)] = window.y + window.height; + } else if (sidenum <= 3) { + sizes[4 + (sidenum*2)] = window.x; + sizes[5 + (sidenum*2)] = window.x + window.width; + } + + /* check constraints */ + for (i = 0; i < 12; i++) { + if (sizes[i] < 0) { + sizes[i] = 0; + } else { + if (i <= 1 || i >= 8) { + if (sizes[i] > display_width) { + sizes[i] = display_width; + } + } else { + if (sizes[i] > display_height) { + sizes[i] = display_height; + } + } + } + } + + XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) &sizes, 4); + + if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) { + XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) &sizes, 12); + } + } +} +#endif /* OWN_WINDOW */ + +#ifdef HAVE_XDBE +void xdbe_swap_buffers(void) +{ + if (use_xdbe) { + //XWindowAttributes dest;//leaks + //XGetWindowAttributes(display, window.window, &dest); + //unsigned int src_height, src_width, src_depth = 0; + //XGetGeometry(display, window.back_buffer, NULL, NULL, NULL,src_width,src_height, NULL, src_depth); +// fprintf(stderr, PACKAGE_NAME": copy from %d x %d x %d to %d x %d x %d\n",src_width, src_height, src_depth, dest.width, dest.height, dest.depth); + XCopyArea(display, window.drawable, window.window, + window.gc_back, 0, 0, window.width, window.height, 0, 0); + /* FIXME should fill w/ window background */ +// XFillRectangle(display, window.back_buffer, window.gc, +// 0, 0, window.width, window.height); + } } +#endif /* HAVE_XDBE */ -#endif /* X11 */