st-background-image-0.8.4.diff (7073B)
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. 5 6 --- 7 config.def.h | 8 +++ 8 x.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++---- 9 2 files changed, 139 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..5ecb8e5 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,7 @@ typedef struct { 51 XVaNestedList spotlist; 52 } ime; 53 Draw draw; 54 + GC bggc; /* Graphics Context for background */ 55 Visual *vis; 56 XSetWindowAttributes attrs; 57 int scr; 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)) { 70 selnotify(e); 71 } 72 + 73 + if (pseudotransparency && 74 + !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 13)) { 75 + updatexy(); 76 + redraw(); 77 + } 78 } 79 80 void 81 @@ -532,7 +544,8 @@ selnotify(XEvent *e) 82 return; 83 } 84 85 - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { 86 + if (e->type == PropertyNotify && nitems == 0 && rem == 0 && 87 + !pseudotransparency) { 88 /* 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 93 * chunk of data. 94 */ 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, 100 &xw.attrs); 101 + } 102 103 /* 104 * Deleting the property is the transfer start signal. 105 @@ -820,9 +835,9 @@ xsetcolorname(int x, const char *name) 106 void 107 xclear(int x1, int y1, int x2, int y2) 108 { 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); 115 } 116 117 void 118 @@ -1207,6 +1222,100 @@ xinit(int cols, int rows) 119 xsel.xtarget = XA_STRING; 120 } 121 122 +void 123 +updatexy() 124 +{ 125 + Window child; 126 + XTranslateCoordinates(xw.dpy, xw.win, DefaultRootWindow(xw.dpy), 0, 0, 127 + &win.x, &win.y, &child); 128 +} 129 + 130 +/* 131 + * load farbfeld file to XImage 132 + */ 133 +XImage* 134 +loadff(const char *filename) 135 +{ 136 + uint32_t i, hdr[4], w, h, size; 137 + uint64_t *data; 138 + FILE *f = fopen(filename, "rb"); 139 + 140 + if (f == NULL) { 141 + fprintf(stderr, "could not load background image.\n"); 142 + return NULL; 143 + } 144 + 145 + if (fread(hdr, sizeof(*hdr), LEN(hdr), f) != LEN(hdr)) 146 + if (ferror(f)) { 147 + fprintf(stderr, "fread:"); 148 + return NULL; 149 + } 150 + else { 151 + fprintf(stderr, "fread: Unexpected end of file\n"); 152 + return NULL; 153 + } 154 + 155 + if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { 156 + fprintf(stderr, "Invalid magic value"); 157 + return NULL; 158 + } 159 + 160 + w = ntohl(hdr[2]); 161 + h = ntohl(hdr[3]); 162 + size = w * h; 163 + data = malloc(size * sizeof(uint64_t)); 164 + 165 + if (fread(data, sizeof(uint64_t), size, f) != size) 166 + if (ferror(f)) { 167 + fprintf(stderr, "fread:"); 168 + return NULL; 169 + } 170 + else { 171 + fprintf(stderr, "fread: Unexpected end of file"); 172 + return NULL; 173 + } 174 + 175 + fclose(f); 176 + 177 + for (i = 0; i < size; i++) 178 + data[i] = (data[i] & 0x00000000000000FF) << 16 | 179 + (data[i] & 0x0000000000FF0000) >> 8 | 180 + (data[i] & 0x000000FF00000000) >> 32; 181 + 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; 186 + return xi; 187 +} 188 + 189 +/* 190 + * initialize background image 191 + */ 192 +void 193 +bginit() 194 +{ 195 + XGCValues gcvalues; 196 + Drawable bgimg; 197 + XImage *bgxi = loadff(bgfile); 198 + 199 + memset(&gcvalues, 0, sizeof(gcvalues)); 200 + xw.bggc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues); 201 + if (!bgxi) return; 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, 205 + bgxi->height); 206 + XDestroyImage(bgxi); 207 + XSetTile(xw.dpy, xw.bggc, bgimg); 208 + XSetFillStyle(xw.dpy, xw.bggc, FillTiled); 209 + if (pseudotransparency) { 210 + updatexy(); 211 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); 212 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); 213 + } 214 +} 215 + 216 int 217 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) 218 { 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); 221 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); 226 + else 227 + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); 228 229 /* Set the clip region because Xft is sometimes dirty. */ 230 r.x = 0; 231 @@ -1855,9 +1967,17 @@ cmessage(XEvent *e) 232 void 233 resize(XEvent *e) 234 { 235 - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) 236 - return; 237 - 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) 242 + return; 243 + updatexy(); 244 + } else { 245 + if (e->xconfigure.width == win.w && 246 + e->xconfigure.height == win.h) 247 + return; 248 + } 249 cresize(e->xconfigure.width, e->xconfigure.height); 250 } 251 252 @@ -2041,6 +2161,7 @@ run: 253 rows = MAX(rows, 1); 254 tnew(cols, rows); 255 xinit(cols, rows); 256 + bginit(); 257 xsetenv(); 258 selinit(); 259 run(); 260 -- 261 2.35.1 262