From 4ce17bbc340ca1f93f9be686f4a796797f9ca6d5 Mon Sep 17 00:00:00 2001 From: Matthias Schoth Date: Sat, 16 Apr 2022 14:21:22 +0200 Subject: [PATCH] Implements background image and pseudo transparancy support. --- config.def.h | 8 +++ x.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 139 insertions(+), 10 deletions(-) diff --git a/config.def.h b/config.def.h index 91ab8ca..ad19e3d 100644 --- a/config.def.h +++ b/config.def.h @@ -8,6 +8,14 @@ static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; +/* + * background image + * expects farbfeld format + * pseudo transparency fixes coordinates to the screen origin + */ +static const char *bgfile = "/path/to/image.ff"; +static const int pseudotransparency = 0; + /* * What program is execed by st depends of these precedence rules: * 1: program passed with -e diff --git a/x.c b/x.c index 8a16faa..fedef53 100644 --- a/x.c +++ b/x.c @@ -14,6 +14,7 @@ #include #include #include +#include char *argv0; #include "arg.h" @@ -81,6 +82,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; typedef struct { int tw, th; /* tty width and height */ int w, h; /* window width and height */ + int x, y; /* window location */ int ch; /* char height */ int cw; /* char width */ int mode; /* window state/mode flags */ @@ -101,6 +103,7 @@ typedef struct { XVaNestedList spotlist; } ime; Draw draw; + GC bggc; /* Graphics Context for background */ Visual *vis; XSetWindowAttributes attrs; int scr; @@ -151,6 +154,9 @@ static void ximinstantiate(Display *, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer); static int xicdestroy(XIC, XPointer, XPointer); static void xinit(int, int); +static void updatexy(void); +static XImage *loadff(const char *); +static void bginit(); static void cresize(int, int); static void xresize(int, int); static void xhints(void); @@ -504,6 +510,12 @@ propnotify(XEvent *e) xpev->atom == clipboard)) { selnotify(e); } + + if (pseudotransparency && + !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 13)) { + updatexy(); + redraw(); + } } void @@ -534,7 +546,8 @@ selnotify(XEvent *e) return; } - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { + if (e->type == PropertyNotify && nitems == 0 && rem == 0 && + !pseudotransparency) { /* * If there is some PropertyNotify with no data, then * this is the signal of the selection owner that all @@ -552,9 +565,11 @@ selnotify(XEvent *e) * when the selection owner does send us the next * chunk of data. */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + if (!pseudotransparency) { + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); + } /* * Deleting the property is the transfer start signal. @@ -835,9 +850,9 @@ xsetcolorname(int x, const char *name) void xclear(int x1, int y1, int x2, int y2) { - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); + if (pseudotransparency) + XSetTSOrigin(xw.dpy, xw.bggc, -win.x, -win.y); + XFillRectangle(xw.dpy, xw.buf, xw.bggc, x1, y1, x2-x1, y2-y1); } void @@ -1223,6 +1238,100 @@ xinit(int cols, int rows) xsel.xtarget = XA_STRING; } +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) +{ + uint32_t i, hdr[4], w, h, size; + uint64_t *data; + FILE *f = fopen(filename, "rb"); + + if (f == NULL) { + fprintf(stderr, "Can not open background image file\n"); + return NULL; + } + + if (fread(hdr, sizeof(*hdr), LEN(hdr), f) != LEN(hdr)) + if (ferror(f)) { + fprintf(stderr, "fread:"); + return NULL; + } + else { + fprintf(stderr, "fread: Unexpected end of file\n"); + return NULL; + } + + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { + fprintf(stderr, "Invalid magic value\n"); + return NULL; + } + + w = ntohl(hdr[2]); + h = ntohl(hdr[3]); + size = w * h; + data = malloc(size * sizeof(uint64_t)); + + if (fread(data, sizeof(uint64_t), size, f) != size) + if (ferror(f)) { + fprintf(stderr, "fread:"); + return NULL; + } + else { + fprintf(stderr, "fread: Unexpected end of file\n"); + return NULL; + } + + fclose(f); + + for (i = 0; i < size; i++) + data[i] = (data[i] & 0x00000000000000FF) << 16 | + (data[i] & 0x0000000000FF0000) >> 8 | + (data[i] & 0x000000FF00000000) >> 32; + + XImage *xi = XCreateImage(xw.dpy, DefaultVisual(xw.dpy, xw.scr), + DefaultDepth(xw.dpy, xw.scr), ZPixmap, 0, + (char *)data, w, h, 32, w * 8); + xi->bits_per_pixel = 64; + return xi; +} + +/* + * initialize background image + */ +void +bginit() +{ + XGCValues gcvalues; + Drawable bgimg; + XImage *bgxi = loadff(bgfile); + + memset(&gcvalues, 0, sizeof(gcvalues)); + xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); + if (!bgxi) return; + 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 (pseudotransparency) { + updatexy(); + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); + } +} + int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { @@ -1463,7 +1572,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i xclear(winx, winy + win.ch, winx + width, win.h); /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + if (bg == &dc.col[defaultbg]) + xclear(winx, winy, winx + width, winy + win.ch); + else + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); /* Set the clip region because Xft is sometimes dirty. */ r.x = 0; @@ -1886,9 +1998,17 @@ cmessage(XEvent *e) void resize(XEvent *e) { - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - + if (pseudotransparency) { + if (e->xconfigure.width == win.w && + e->xconfigure.height == win.h && + e->xconfigure.x == win.x && e->xconfigure.y == win.y) + return; + updatexy(); + } else { + if (e->xconfigure.width == win.w && + e->xconfigure.height == win.h) + return; + } cresize(e->xconfigure.width, e->xconfigure.height); } @@ -2072,6 +2192,7 @@ run: rows = MAX(rows, 1); tnew(cols, rows); xinit(cols, rows); + bginit(); xsetenv(); selinit(); run(); -- 2.35.1