st-background-image-0.8.4.diff (7803B)
1 From ac472ae8b588b8ef6be7cbdd4487210f07349a3c 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. 5 6 --- 7 config.def.h | 8 +++ 8 x.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++--- 9 2 files changed, 166 insertions(+), 10 deletions(-) 10 11 diff --git a/config.def.h b/config.def.h 12 index 6f05dce..3d352db 100644 13 --- a/config.def.h 14 +++ b/config.def.h 15 @@ -8,6 +8,14 @@ 16 static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; 17 static int borderpx = 2; 18 19 +/* 20 + * background image 21 + * expects farbfeld format 22 + * pseudo transparency fixes coordinates to the screen origin 23 + */ 24 +static const char *bgfile = "/path/to/image.ff"; 25 +static const int pseudotransparency = 0; 26 + 27 /* 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..a5fc827 100644 32 --- a/x.c 33 +++ b/x.c 34 @@ -14,6 +14,7 @@ 35 #include <X11/keysym.h> 36 #include <X11/Xft/Xft.h> 37 #include <X11/XKBlib.h> 38 +#include <arpa/inet.h> 39 40 char *argv0; 41 #include "arg.h" 42 @@ -81,6 +82,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; 43 typedef struct { 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,8 @@ typedef struct { 51 XVaNestedList spotlist; 52 } ime; 53 Draw draw; 54 + GC bggc; /* Graphics Context for background */ 55 + Pixmap bgpmap; /* background image pixmap */ 56 Visual *vis; 57 XSetWindowAttributes attrs; 58 int scr; 59 @@ -151,6 +155,9 @@ static void ximinstantiate(Display *, XPointer, XPointer); 60 static void ximdestroy(XIM, XPointer, XPointer); 61 static int xicdestroy(XIC, XPointer, XPointer); 62 static void xinit(int, int); 63 +static void updatexy(void); 64 +static XImage *loadff(const char *); 65 +static void bginit(); 66 static void cresize(int, int); 67 static void xresize(int, int); 68 static void xhints(void); 69 @@ -502,6 +509,12 @@ propnotify(XEvent *e) 70 xpev->atom == clipboard)) { 71 selnotify(e); 72 } 73 + 74 + if (pseudotransparency && 75 + !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 13)) { 76 + updatexy(); 77 + redraw(); 78 + } 79 } 80 81 void 82 @@ -532,7 +545,8 @@ selnotify(XEvent *e) 83 return; 84 } 85 86 - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { 87 + if (e->type == PropertyNotify && nitems == 0 && rem == 0 && 88 + !pseudotransparency) { 89 /* 90 * If there is some PropertyNotify with no data, then 91 * this is the signal of the selection owner that all 92 @@ -550,9 +564,11 @@ selnotify(XEvent *e) 93 * when the selection owner does send us the next 94 * chunk of data. 95 */ 96 - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); 97 - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, 98 + if (!pseudotransparency) { 99 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); 100 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, 101 &xw.attrs); 102 + } 103 104 /* 105 * Deleting the property is the transfer start signal. 106 @@ -820,9 +836,9 @@ xsetcolorname(int x, const char *name) 107 void 108 xclear(int x1, int y1, int x2, int y2) 109 { 110 - XftDrawRect(xw.draw, 111 - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], 112 - x1, y1, x2-x1, y2-y1); 113 + if (pseudotransparency) 114 + XSetTSOrigin(xw.dpy, xw.bggc, -win.x, -win.y); 115 + XFillRectangle(xw.dpy, xw.buf, xw.bggc, x1, y1, x2-x1, y2-y1); 116 } 117 118 void 119 @@ -1207,6 +1223,126 @@ xinit(int cols, int rows) 120 xsel.xtarget = XA_STRING; 121 } 122 123 +void 124 +updatexy() 125 +{ 126 + Window child; 127 + XTranslateCoordinates(xw.dpy, xw.win, DefaultRootWindow(xw.dpy), 0, 0, 128 + &win.x, &win.y, &child); 129 +} 130 + 131 +/* 132 + * load farbfeld file to XImage 133 + */ 134 +XImage* 135 +loadff(const char *filename) 136 +{ 137 + uint32_t i, hdr[4], w, h, size; 138 + uint64_t npixels, *data; 139 + FILE *f; 140 + XImage *xi; 141 + 142 + if (!(f = fopen(filename, "rb"))) { 143 + fprintf(stderr, "could not load background image.\n"); 144 + return NULL; 145 + } 146 + 147 + if (fread(hdr, sizeof(*hdr), LEN(hdr), f) != LEN(hdr)) { 148 + fprintf(stderr, "fread: %s\n", ferror(f) ? "read error" : 149 + "unexpected end of file"); 150 + fclose(f); 151 + return NULL; 152 + } 153 + 154 + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { 155 + fprintf(stderr, "Invalid magic value\n"); 156 + fclose(f); 157 + return NULL; 158 + } 159 + 160 + w = ntohl(hdr[2]); 161 + h = ntohl(hdr[3]); 162 + npixels = (uint64_t)w * h; 163 + if (w == 0 || h == 0 || w > INT_MAX / 8 || 164 + npixels > UINT32_MAX || npixels > SIZE_MAX / sizeof(*data)) { 165 + fprintf(stderr, "Invalid image dimensions\n"); 166 + fclose(f); 167 + return NULL; 168 + } 169 + size = w * h; 170 + 171 + data = malloc(size * sizeof(*data)); 172 + if (!data) { 173 + fprintf(stderr, "malloc: %s\n", strerror(errno)); 174 + fclose(f); 175 + return NULL; 176 + } 177 + 178 + if (fread(data, sizeof(*data), size, f) != size) { 179 + fprintf(stderr, "fread: %s\n", ferror(f) ? "read error" : 180 + "unexpected end of file"); 181 + free(data); 182 + fclose(f); 183 + return NULL; 184 + } 185 + fclose(f); 186 + 187 + for (i = 0; i < size; i++) 188 + data[i] = (data[i] & 0x00000000000000FF) << 16 | 189 + (data[i] & 0x0000000000FF0000) >> 8 | 190 + (data[i] & 0x000000FF00000000) >> 32; 191 + 192 + xi = XCreateImage(xw.dpy, DefaultVisual(xw.dpy, xw.scr), 193 + DefaultDepth(xw.dpy, xw.scr), ZPixmap, 0, 194 + (char *)data, w, h, 32, w * 8); 195 + if (!xi) { 196 + free(data); 197 + return NULL; 198 + } 199 + xi->bits_per_pixel = 64; 200 + return xi; 201 +} 202 + 203 +/* 204 + * initialize background image 205 + */ 206 +void 207 +bginit() 208 +{ 209 + XGCValues gcvalues; 210 + XImage *bgxi = loadff(bgfile); 211 + 212 + if (!bgxi) { 213 + if (xw.bggc) 214 + return; 215 + memset(&gcvalues, 0, sizeof(gcvalues)); 216 + xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); 217 + XSetForeground(xw.dpy, xw.bggc, dc.col[defaultbg].pixel); 218 + XSetFillStyle(xw.dpy, xw.bggc, FillSolid); 219 + return; 220 + } 221 + 222 + if (xw.bggc) 223 + XFreeGC(xw.dpy, xw.bggc); 224 + if (xw.bgpmap) 225 + XFreePixmap(xw.dpy, xw.bgpmap); 226 + 227 + memset(&gcvalues, 0, sizeof(gcvalues)); 228 + xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); 229 + xw.bgpmap = XCreatePixmap(xw.dpy, xw.win, bgxi->width, bgxi->height, 230 + DefaultDepth(xw.dpy, xw.scr)); 231 + XPutImage(xw.dpy, xw.bgpmap, dc.gc, bgxi, 0, 0, 0, 0, bgxi->width, 232 + bgxi->height); 233 + XDestroyImage(bgxi); 234 + XSetTile(xw.dpy, xw.bggc, xw.bgpmap); 235 + XSetFillStyle(xw.dpy, xw.bggc, FillTiled); 236 + if (pseudotransparency) { 237 + updatexy(); 238 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); 239 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); 240 + } 241 +} 242 + 243 int 244 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) 245 { 246 @@ -1447,7 +1583,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i 247 xclear(winx, winy + win.ch, winx + width, win.h); 248 249 /* Clean up the region we want to draw to. */ 250 - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); 251 + if (bg == &dc.col[defaultbg]) 252 + xclear(winx, winy, winx + width, winy + win.ch); 253 + else 254 + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); 255 256 /* Set the clip region because Xft is sometimes dirty. */ 257 r.x = 0; 258 @@ -1855,9 +1994,17 @@ cmessage(XEvent *e) 259 void 260 resize(XEvent *e) 261 { 262 - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) 263 - return; 264 - 265 + if (pseudotransparency) { 266 + if (e->xconfigure.width == win.w && 267 + e->xconfigure.height == win.h && 268 + e->xconfigure.x == win.x && e->xconfigure.y == win.y) 269 + return; 270 + updatexy(); 271 + } else { 272 + if (e->xconfigure.width == win.w && 273 + e->xconfigure.height == win.h) 274 + return; 275 + } 276 cresize(e->xconfigure.width, e->xconfigure.height); 277 } 278 279 @@ -2041,6 +2188,7 @@ run: 280 rows = MAX(rows, 1); 281 tnew(cols, rows); 282 xinit(cols, rows); 283 + bginit(); 284 xsetenv(); 285 selinit(); 286 run(); 287 -- 288 2.55.0 289