1 From 2c984d74ca15806dcfa174b7e75f48c0d01a49bf Mon Sep 17 00:00:00 2001
2 From: Matthias Schoth <mschoth@gmail.com>
3 Date: Thu, 17 Feb 2022 00:23:23 +0100
4 Subject: [PATCH] Implements background image and pseudo transparancy support.
8 x.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++----
9 2 files changed, 139 insertions(+), 10 deletions(-)
11 diff --git a/config.def.h b/config.def.h
12 index 6f05dce..3d352db 100644
16 static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
17 static int borderpx = 2;
21 + * expects farbfeld format
22 + * pseudo transparency fixes coordinates to the screen origin
24 +static const char *bgfile = "/path/to/image.ff";
25 +static const int pseudotransparency = 0;
28 * What program is execed by st depends of these precedence rules:
29 * 1: program passed with -e
30 diff --git a/x.c b/x.c
31 index 210f184..5ecb8e5 100644
35 #include <X11/keysym.h>
36 #include <X11/Xft/Xft.h>
37 #include <X11/XKBlib.h>
38 +#include <arpa/inet.h>
42 @@ -81,6 +82,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
44 int tw, th; /* tty width and height */
45 int w, h; /* window width and height */
46 + int x, y; /* window location */
47 int ch; /* char height */
48 int cw; /* char width */
49 int mode; /* window state/mode flags */
50 @@ -101,6 +103,7 @@ typedef struct {
51 XVaNestedList spotlist;
54 + GC bggc; /* Graphics Context for background */
56 XSetWindowAttributes attrs;
58 @@ -151,6 +154,9 @@ static void ximinstantiate(Display *, XPointer, XPointer);
59 static void ximdestroy(XIM, XPointer, XPointer);
60 static int xicdestroy(XIC, XPointer, XPointer);
61 static void xinit(int, int);
62 +static void updatexy(void);
63 +static XImage *loadff(const char *);
64 +static void bginit();
65 static void cresize(int, int);
66 static void xresize(int, int);
67 static void xhints(void);
68 @@ -502,6 +508,12 @@ propnotify(XEvent *e)
69 xpev->atom == clipboard)) {
73 + if (pseudotransparency &&
74 + !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 13)) {
81 @@ -532,7 +544,8 @@ selnotify(XEvent *e)
85 - if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
86 + if (e->type == PropertyNotify && nitems == 0 && rem == 0 &&
87 + !pseudotransparency) {
89 * If there is some PropertyNotify with no data, then
90 * this is the signal of the selection owner that all
91 @@ -550,9 +563,11 @@ selnotify(XEvent *e)
92 * when the selection owner does send us the next
95 - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
96 - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
97 + if (!pseudotransparency) {
98 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
99 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
104 * Deleting the property is the transfer start signal.
105 @@ -820,9 +835,9 @@ xsetcolorname(int x, const char *name)
107 xclear(int x1, int y1, int x2, int y2)
109 - XftDrawRect(xw.draw,
110 - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg],
111 - x1, y1, x2-x1, y2-y1);
112 + if (pseudotransparency)
113 + XSetTSOrigin(xw.dpy, xw.bggc, -win.x, -win.y);
114 + XFillRectangle(xw.dpy, xw.buf, xw.bggc, x1, y1, x2-x1, y2-y1);
118 @@ -1207,6 +1222,100 @@ xinit(int cols, int rows)
119 xsel.xtarget = XA_STRING;
126 + XTranslateCoordinates(xw.dpy, xw.win, DefaultRootWindow(xw.dpy), 0, 0,
127 + &win.x, &win.y, &child);
131 + * load farbfeld file to XImage
134 +loadff(const char *filename)
136 + uint32_t i, hdr[4], w, h, size;
138 + FILE *f = fopen(filename, "rb");
141 + fprintf(stderr, "could not load background image.\n");
145 + if (fread(hdr, sizeof(*hdr), LEN(hdr), f) != LEN(hdr))
147 + fprintf(stderr, "fread:");
151 + fprintf(stderr, "fread: Unexpected end of file\n");
155 + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) {
156 + fprintf(stderr, "Invalid magic value");
163 + data = malloc(size * sizeof(uint64_t));
165 + if (fread(data, sizeof(uint64_t), size, f) != size)
167 + fprintf(stderr, "fread:");
171 + fprintf(stderr, "fread: Unexpected end of file");
177 + for (i = 0; i < size; i++)
178 + data[i] = (data[i] & 0x00000000000000FF) << 16 |
179 + (data[i] & 0x0000000000FF0000) >> 8 |
180 + (data[i] & 0x000000FF00000000) >> 32;
182 + XImage *xi = XCreateImage(xw.dpy, DefaultVisual(xw.dpy, xw.scr),
183 + DefaultDepth(xw.dpy, xw.scr), ZPixmap, 0,
184 + (char *)data, w, h, 32, w * 8);
185 + xi->bits_per_pixel = 64;
190 + * initialize background image
195 + XGCValues gcvalues;
197 + XImage *bgxi = loadff(bgfile);
199 + memset(&gcvalues, 0, sizeof(gcvalues));
200 + xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues);
202 + bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi->width, bgxi->height,
203 + DefaultDepth(xw.dpy, xw.scr));
204 + XPutImage(xw.dpy, bgimg, dc.gc, bgxi, 0, 0, 0, 0, bgxi->width,
206 + XDestroyImage(bgxi);
207 + XSetTile(xw.dpy, xw.bggc, bgimg);
208 + XSetFillStyle(xw.dpy, xw.bggc, FillTiled);
209 + if (pseudotransparency) {
211 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
212 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
217 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
219 @@ -1447,7 +1556,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
220 xclear(winx, winy + win.ch, winx + width, win.h);
222 /* Clean up the region we want to draw to. */
223 - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
224 + if (bg == &dc.col[defaultbg])
225 + xclear(winx, winy, winx + width, winy + win.ch);
227 + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
229 /* Set the clip region because Xft is sometimes dirty. */
231 @@ -1855,9 +1967,17 @@ cmessage(XEvent *e)
235 - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
238 + if (pseudotransparency) {
239 + if (e->xconfigure.width == win.w &&
240 + e->xconfigure.height == win.h &&
241 + e->xconfigure.x == win.x && e->xconfigure.y == win.y)
245 + if (e->xconfigure.width == win.w &&
246 + e->xconfigure.height == win.h)
249 cresize(e->xconfigure.width, e->xconfigure.height);
252 @@ -2041,6 +2161,7 @@ run: