#include "torsmo.h" #include #include #include #ifdef XFT #include #endif #ifdef XDBE int use_xdbe; #endif #ifdef XFT int use_xft; #endif /* some basic X11 stuff */ Display *display; int display_width; int display_height; int screen; /* workarea from _NET_WORKAREA, this is where window / text is aligned */ int workarea[4]; /* Window stuff */ struct torsmo_window window; /* local prototypes */ static void update_workarea(); static Window find_window_to_draw(); static Window find_subwindow(Window win, int w, int h); /* X11 initializer */ void init_X11() { if ((display=XOpenDisplay(0)) == NULL) CRIT_ERR("can't open display: %s", XDisplayName(0)); screen = DefaultScreen(display); display_width = DisplayWidth(display, screen); display_height = DisplayHeight(display, screen); update_workarea(); } static void update_workarea() { 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) { long desktop = * (long *) buf; XFree(buf); buf = 0; /* get workarea */ if (XGetWindowProperty(display, root, ATOM(_NET_WORKAREA), desktop*4, 4, False, XA_CARDINAL, &type, &format, &nitems, &bytes, &buf) == Success && type == XA_CARDINAL) { workarea[0] = ((long *) buf)[0]; workarea[1] = ((long *) buf)[1]; workarea[2] = ((long *) buf)[2]; workarea[3] = ((long *) buf)[3]; } } if (buf) { XFree(buf); buf = 0; } } static Window find_window_to_draw() { Atom type; int format, i; unsigned long nitems, bytes; unsigned int n; Window root = RootWindow(display, screen); Window win = root; Window troot, parent, *children; unsigned char *buf = NULL; /* 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) { win = * (Window *) buf; XFree(buf); XFree(children); fprintf(stderr, "torsmo: drawing to window from __SWM_VROOT property\n"); return win; } if (buf) { XFree(buf); buf = 0; } } XFree(children); /* get subwindows from root */ win = find_subwindow(root, -1, -1); update_workarea(); win = find_subwindow(win, workarea[2], workarea[3]); if (buf) { XFree(buf); buf = 0; } if (win != root) fprintf(stderr, "torsmo: drawing to subwindow of root window (%lx)\n", win); else fprintf(stderr, "torsmo: drawing to root window\n"); return win; } /* sets background to ParentRelative for the Window and all parents */ void set_transparent_background(Window win) { Window parent = win; unsigned int i; for (i=0; i<16 && parent != RootWindow(display, screen); i++) { Window r, *children; unsigned int n; XSetWindowBackgroundPixmap(display, parent, ParentRelative); XQueryTree(display, parent, &r, &parent, &children, &n); XFree(children); } XClearWindow(display, win); } void init_window(int own_window, int w, int h) { /* 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. */ #ifdef OWN_WINDOW if (own_window) { /* looks like root pixmap isn't needed for anything */ { XSetWindowAttributes attrs; XClassHint class_hints; /* just test color */ attrs.background_pixel = get_x11_color("green"); window.window = XCreateWindow(display, RootWindow(display, screen), window.x, window.y, w, h, 0, CopyFromParent, /* depth */ CopyFromParent, /* class */ CopyFromParent, /* visual */ CWBackPixel, &attrs); class_hints.res_class = "Torsmo"; class_hints.res_name = "torsmo"; XSetClassHint(display, window.window, &class_hints); set_transparent_background(window.window); XStoreName(display, window.window, "Torsmo"); XClearWindow(display, window.window); XMoveWindow(display, window.window, window.x, window.y); } { /* turn off decorations */ Atom a = XInternAtom(display, "_MOTIF_WM_HINTS", True); if (a != None) { long prop[5] = { 2, 0, 0, 0, 0 }; XChangeProperty(display, window.window, a, a, 32, PropModeReplace, (unsigned char *) prop, 5); } /* set window sticky (to all desktops) */ a = XInternAtom(display, "_NET_WM_DESKTOP", True); if (a != None) { long prop = 0xFFFFFFFF; XChangeProperty(display, window.window, a, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &prop, 1); } } XMapWindow(display, window.window); } else #endif /* root / desktop window */ { XWindowAttributes attrs; if (!window.window) window.window = find_window_to_draw(); if (XGetWindowAttributes(display, window.window, &attrs)) { window.width = attrs.width; window.height = attrs.height; } } /* Drawable is same as window. This may be changed by double buffering. */ window.drawable = window.window; #ifdef XDBE if (use_xdbe) { int major, minor; if (!XdbeQueryExtension(display, &major, &minor)) { use_xdbe = 0; } else { window.back_buffer = XdbeAllocateBackBufferName(display, window.window, XdbeBackground); if (window.back_buffer != None) { window.drawable = window.back_buffer; fprintf(stderr, "torsmo: drawing to double buffer\n"); } else use_xdbe = 0; } if (!use_xdbe) ERR("failed to set up double buffer"); } if (!use_xdbe) fprintf(stderr, "torsmo: drawing to single buffer\n"); #endif XFlush(display); /* set_transparent_background() 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 #ifdef OWN_WINDOW | (own_window ? (StructureNotifyMask | PropertyChangeMask) : 0) #endif ); } static Window find_subwindow(Window win, int w, int h) { unsigned int i, j; Window troot, parent, *children; unsigned int n; /* search subwindows with same size as display or work area */ for (i=0; i<10; i++) { XQueryTree(display, win, &troot, &parent, &children, &n); for (j=0; j