module patch.background_image; import st; import x; import config; import patches; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; import deimos.X11.Xlib; import deimos.X11.X; import deimos.X11.Xutil; static if (isPatchEnabled!"BACKGROUND_IMAGE_PATCH") { import core.sys.posix.arpa.inet : ntohl; void updatexy() { Window child; XTranslateCoordinates(xw.dpy, xw.win, DefaultRootWindow(xw.dpy), 0, 0, &win.x, &win.y, &child); } /* * load farbfeld file to XImage */ XImage* loadff(const(char)* filename) { uint[4] hdr; uint w, h, size; ulong* data; FILE* f = fopen(filename, "rb".ptr); if (f is null) { fprintf(stderr, "could not load background image.\n"); return null; } if (fread(hdr.ptr, uint.sizeof, hdr.length, f) != hdr.length) { fprintf(stderr, "fread: %s\n", ferror(f) ? "".ptr : "Unexpected end of file reading header"); fclose(f); return null; } if (memcmp("farbfeld".ptr, hdr.ptr, "farbfeld".length - 1) != 0) { fprintf(stderr, "Invalid magic value\n"); fclose(f); return null; } w = ntohl(hdr[2]); h = ntohl(hdr[3]); size = w * h; data = cast(ulong*)xmalloc(size * ulong.sizeof); if (fread(data, ulong.sizeof, size, f) != size) { fprintf(stderr, "fread: %s\n", ferror(f) ? "".ptr : "Unexpected end of file reading data"); fclose(f); free(data); return null; } fclose(f); for (uint i = 0; i < size; i++) { data[i] = (data[i] & 0x00000000000000FF) << 16 | (data[i] & 0x0000000000FF0000) >> 8 | (data[i] & 0x000000FF00000000) >> 32 | (data[i] & 0x00FF000000000000) >> 24; } static if (isPatchEnabled!"ALPHA_PATCH") { XImage* xi = XCreateImage(xw.dpy, xw.vis, xw.depth, ZPixmap, 0, cast(char*)data, w, h, 32, w * 8); } else { XImage* xi = XCreateImage(xw.dpy, DefaultVisual(xw.dpy, xw.scr), DefaultDepth(xw.dpy, xw.scr), ZPixmap, 0, cast(char*)data, w, h, 32, w * 8); } xi.bits_per_pixel = 64; return xi; } /* * initialize background image */ extern(C) void bginit() { XGCValues gcvalues; Drawable bgimg; XImage* bgxi = loadff(config.bgfile.ptr); memset(&gcvalues, 0, XGCValues.sizeof); xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); if (!bgxi) return; static if (isPatchEnabled!"ALPHA_PATCH") { bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi.width, bgxi.height, xw.depth); } else { bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi.width, bgxi.height, DefaultDepth(xw.dpy, xw.scr)); } XPutImage(xw.dpy, bgimg, dc.gc, bgxi, 0, 0, 0, 0, bgxi.width, bgxi.height); XDestroyImage(bgxi); XSetTile(xw.dpy, xw.bggc, bgimg); XSetFillStyle(xw.dpy, xw.bggc, FillTiled); if (config.pseudotransparency) { updatexy(); xw.attrs.event_mask |= PropertyChangeMask; XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } } static if (isPatchEnabled!"BACKGROUND_IMAGE_RELOAD_PATCH") { void reload_image() { XGCValues gcvalues; Drawable bgimg; // Recreate background GC if (xw.bggc) XFreeGC(xw.dpy, xw.bggc); memset(&gcvalues, 0, XGCValues.sizeof); xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); XImage* bgxi = loadff(config.bgfile.ptr); if (!bgxi) return; static if (isPatchEnabled!"ALPHA_PATCH") { bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi.width, bgxi.height, xw.depth); } else { bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi.width, bgxi.height, DefaultDepth(xw.dpy, xw.scr)); } XPutImage(xw.dpy, bgimg, dc.gc, bgxi, 0, 0, 0, 0, bgxi.width, bgxi.height); XDestroyImage(bgxi); XSetTile(xw.dpy, xw.bggc, bgimg); XSetFillStyle(xw.dpy, xw.bggc, FillTiled); if (config.pseudotransparency) { updatexy(); } redraw(); } } }