X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fx11.c;h=cc37c0e44867bf897306e51cdf5db8ae0f77448c;hb=72c9a740c77f3e73e2d104add63890ee7df13b43;hp=8a93a41dd29fd309f7c3b2da1d7c3dcf2d389960;hpb=88ae603cf57afdb450c87d1da440f2bb88fe64a8;p=monky diff --git a/src/x11.c b/src/x11.c index 8a93a41..cc37c0e 100644 --- a/src/x11.c +++ b/src/x11.c @@ -1,4 +1,7 @@ -/* Conky, a system monitor, based on torsmo +/* -*- 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 * * Any original torsmo code is licensed under the BSD license * @@ -7,7 +10,7 @@ * Please see COPYING for details * * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen - * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al. + * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. * (see AUTHORS) * All rights reserved. * @@ -41,13 +44,19 @@ #ifdef XFT #include -int use_xft = 0; +int use_xft; #endif #ifdef HAVE_XDBE int use_xdbe; #endif +#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 = NULL; int display_width; @@ -61,6 +70,7 @@ int workarea[4]; /* Window stuff */ struct conky_window window; +char window_created = 0; /* local prototypes */ static void update_workarea(void); @@ -72,7 +82,7 @@ void init_X11(const char *disp) { if (!display) { if ((display = XOpenDisplay(disp)) == NULL) { - CRIT_ERR("can't open display: %s", XDisplayName(0)); + CRIT_ERR(NULL, NULL, "can't open display: %s", XDisplayName(disp)); } } @@ -80,39 +90,18 @@ void init_X11(const char *disp) display_width = DisplayWidth(display, screen); display_height = DisplayHeight(display, screen); + get_x11_desktop_info(display, 0); + 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. @@ -139,14 +128,14 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) 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) + False, XA_WINDOW, &type, &format, &nitems, &bytes, &buf) == Success && type == XA_WINDOW) { win = *(Window *) buf; XFree(buf); XFree(children); fprintf(stderr, - PACKAGE_NAME": 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; @@ -174,8 +163,8 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) if (win != root) { fprintf(stderr, - PACKAGE_NAME": desktop window (%lx) is subwindow of root window (%lx)\n", - win, root); + 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); } @@ -188,10 +177,26 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) return win; } -/* sets background to ParentRelative for the Window and all parents */ -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; @@ -210,14 +215,58 @@ void set_transparent_background(Window win) XSetWindowBackground(display, win, background_colour); colour_set = background_colour; } - // XClearWindow(display, win); not sure why this was here +#ifdef USE_ARGB + } +#endif /* USE_ARGB */ +} + +#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 destroy_window(void) { - XDestroyWindow(display, window.window); - XFreeGC(display, window.gc); +#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, @@ -228,13 +277,33 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, * happens but I bet the bug is somewhere here. */ set_transparent = set_trans; background_colour = back_colour; + window_created = 1; #ifdef OWN_WINDOW if (own_window) { + 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. @@ -242,11 +311,21 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, 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, CopyFromParent, InputOutput, CopyFromParent, - CWBackPixel | CWOverrideRedirect, &attrs); + window.y, w, h, 0, depth, InputOutput, visual, + flags, &attrs); XLowerWindow(display, window.window); @@ -258,19 +337,32 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, * Process hints and buttons. */ XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, Always, 0L, 0L, False, StructureNotifyMask | ExposureMask | - ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 }; + ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 }; XClassHint classHint; XWMHints wmHint; Atom xa; +#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, CopyFromParent, InputOutput, CopyFromParent, - CWBackPixel | CWOverrideRedirect, &attrs); + window.y, w, h, 0, depth, InputOutput, visual, + flags, &attrs); classHint.res_name = window.class_name; classHint.res_class = classHint.res_name; @@ -279,14 +371,15 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, /* 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) { + if (window.type == TYPE_DOCK || window.type == TYPE_PANEL) { wmHint.initial_state = WithdrawnState; - } else { + } 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); @@ -319,7 +412,7 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, break; } XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeReplace, (unsigned char *) &prop, 1); + PropModeReplace, (unsigned char *) &prop, 1); } /* Set desired hints */ @@ -327,27 +420,27 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, /* Window decorations */ if (TEST_HINT(window.hints, HINT_UNDECORATED)) { /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n"); - fflush(stderr); */ + 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); + PropModeReplace, (unsigned char *) prop, 5); } } /* Below other windows */ if (TEST_HINT(window.hints, HINT_BELOW)) { /* fprintf(stderr, PACKAGE_NAME": hint - below\n"); - fflush(stderr); */ + 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); + PropModeAppend, (unsigned char *) &prop, 1); } xa = ATOM(_NET_WM_STATE); @@ -355,21 +448,21 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &xa_prop, 1); + PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Above other windows */ if (TEST_HINT(window.hints, HINT_ABOVE)) { /* fprintf(stderr, PACKAGE_NAME": hint - above\n"); - fflush(stderr); */ + 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); + PropModeAppend, (unsigned char *) &prop, 1); } xa = ATOM(_NET_WM_STATE); @@ -377,21 +470,21 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &xa_prop, 1); + PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Sticky */ if (TEST_HINT(window.hints, HINT_STICKY)) { /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n"); - fflush(stderr); */ + 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); + PropModeAppend, (unsigned char *) &xa_prop, 1); } xa = ATOM(_NET_WM_STATE); @@ -399,61 +492,65 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &xa_prop, 1); + PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Skip taskbar */ if (TEST_HINT(window.hints, HINT_SKIP_TASKBAR)) { /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n"); - fflush(stderr); */ + 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); + PropModeAppend, (unsigned char *) &xa_prop, 1); } } /* Skip pager */ - if (TEST_HINT(window.hints, HINT_SKIP_PAGER)) { - /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n"); - fflush(stderr); */ + 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_SKIP_PAGER); + Atom xa_prop = ATOM(_NET_WM_STATE_FULLSCREEN); XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &xa_prop, 1); + PropModeAppend, (unsigned char *) &xa_prop, 1); } } - } /* else { window.type != TYPE_OVERRIDE */ + } fprintf(stderr, PACKAGE_NAME": drawing to created window (0x%lx)\n", - window.window); + window.window); fflush(stderr); XMapWindow(display, window.window); - } else /* if (own_window) { */ -#endif - /* root / desktop window */ + } else +#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); + 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, PACKAGE_NAME": drawing to desktop window\n"); } /* Drawable is same as window. This may be changed by double buffering. */ @@ -461,30 +558,24 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, #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, PACKAGE_NAME": drawing to double buffer\n"); + 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) { - ERR("failed to set up double buffer"); + NORM_ERR("failed to set up double buffer"); } } if (!use_xdbe) { fprintf(stderr, PACKAGE_NAME": drawing to single buffer\n"); } #endif - window.visual = DefaultVisual(display, DefaultScreen(display)); - window.colourmap = DefaultColormap(display, DefaultScreen(display)); #ifdef IMLIB2 { cimlib_init(display, window.drawable, window.visual, window.colourmap); @@ -492,21 +583,12 @@ void init_window(int own_window, int w, int h, int set_trans, int back_colour, #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) @@ -527,8 +609,8 @@ static Window find_subwindow(Window win, int w, int h) /* 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))) { + && attrs.height == display_height) + || (attrs.width == w && attrs.height == h))) { win = children[j]; break; } @@ -544,32 +626,6 @@ static Window find_subwindow(Window win, int w, int h) return win; } -long get_x11_color(const char *name) -{ - 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[DEFAULT_TEXT_BUFFER_SIZE]; - - newname[0] = '#'; - strncpy(&newname[1], name, DEFAULT_TEXT_BUFFER_SIZE - 1); - /* now lets try again */ - if (!XParseColor(display, DefaultColormap(display, screen), &newname[0], - &color)) { - ERR("can't parse X color '%s'", name); - return 0xFF00FF; - } - } - if (!XAllocColor(display, DefaultColormap(display, screen), &color)) { - ERR("can't allocate X color '%s'", name); - } - - return (long) color.pixel; -} - void create_gc(void) { XGCValues values; @@ -577,78 +633,168 @@ void create_gc(void) values.graphics_exposures = 0; values.function = GXcopy; window.gc = XCreateGC(display, window.drawable, - GCFunction | GCGraphicsExposures, &values); + GCFunction | GCGraphicsExposures, &values); + window.gc_back = XCreateGC(display, window.drawable, + GCFunction | GCGraphicsExposures, &values); } -void update_x11info(void) +//Get current desktop number +static inline void get_x11_desktop_current(Display *current_display, Window root, Atom atom) { - Window root; - Atom actual_type, 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.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; - current_info->x11.monitor.number = XScreenCount(display); - current_info->x11.monitor.current = XDefaultScreen(display); - root = RootWindow(display, current_info->x11.monitor.current); - - //Get current desktop number - if ((atom = XInternAtom(display, "_NET_CURRENT_DESKTOP", True)) != None) { - if ( (XGetWindowProperty( display, root, atom, - 0, 1L, False, XA_CARDINAL, - &actual_type, &actual_format, &nitems, - &bytes_after, &prop ) == Success ) && - (actual_type == XA_CARDINAL) && - (nitems == 1L) ) { - current_info->x11.desktop.current = prop[0]+1; - } + 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; - //Get total number of available desktops - if ((atom = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", True)) != None) { - if ( (XGetWindowProperty( display, root, atom, - 0, 1L, False, XA_CARDINAL, - &actual_type, &actual_format, &nitems, - &bytes_after, &prop ) == Success ) && - (actual_type == XA_CARDINAL) && - (nitems == 1L) ) { - current_info->x11.desktop.number = prop[0]; - } + 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); + } +} - //Get current desktop name - if ((atom = XInternAtom(display, "_NET_DESKTOP_NAMES", True)) != None) { - if ( (XGetWindowProperty( 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) ) { - unsigned int i = 0, j = 0; - int k = 0; - while ( i < nitems ) { - if ( prop[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); - //desktop names can be empty but should always be not null - strcpy( current_info->x11.desktop.name, (char *)&prop[j] ); - break; +//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; } - j = i; - } - } - } } +} +void get_x11_desktop_info(Display *current_display, Atom atom) +{ + 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) { @@ -661,29 +807,21 @@ void set_struts(int sidenum) /* 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 */ @@ -721,3 +859,26 @@ void set_struts(int sidenum) } } } +#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 */ + XSet +/* + XFillRectangle(display, window.back_buffer, window.gc, + 0, 0, window.width, window.height); +*/ + } +} +#endif /* HAVE_XDBE */ +