commit 1a8175a33718b87bebbb831231abd8b8219689fb
parent 51dc6ba469cf4e05496665c6a957cf4d5a5f9bf9
Author: bakkeby <bakkeby@gmail.com>
Date: Thu, 10 Mar 2022 11:37:49 +0100
Adding background image patch
Diffstat:
9 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
@@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog:
+2022-03-10 - Added the background image patch
+
2022-02-24 - Upgraded to st 0.8.5 e823e23, 2022-02-17 - removing osc_10_11_12_2 patch as no longer relevant
2021-08-18 - Added the CSI 22 & 23 patch
@@ -95,6 +97,10 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
- a patch that aims to prevent black bars being drawn on the edges of st terminals using the
anysize patch
+ - [background-image](https://st.suckless.org/patches/background_image/)
+ - draws a background image in farbfeld format in place of the defaultbg color allowing for
+ pseudo transparency
+
- [blinking-cursor](https://st.suckless.org/patches/blinking_cursor/)
- allows the use of a blinking cursor
diff --git a/config.def.h b/config.def.h
@@ -14,6 +14,16 @@ static char *font2[] = {
};
#endif // FONT2_PATCH
+#if BACKGROUND_IMAGE_PATCH
+/*
+ * 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;
+#endif // BACKGROUND_IMAGE_PATCH
+
#if RELATIVEBORDER_PATCH
/* borderperc: percentage of cell width to use as a border
* 0 = no border, 100 = border width is same as cell width */
diff --git a/patch/background_image_x.c b/patch/background_image_x.c
@@ -0,0 +1,104 @@
+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, "could not load background image.\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");
+ 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");
+ return NULL;
+ }
+
+ fclose(f);
+
+ for (i = 0; i < size; i++)
+ data[i] = (data[i] & 0x00000000000000FF) << 16 |
+ (data[i] & 0x0000000000FF0000) >> 8 |
+ (data[i] & 0x000000FF00000000) >> 32 |
+ (data[i] & 0x00FF000000000000) >> 24;
+
+ #if ALPHA_PATCH
+ XImage *xi = XCreateImage(xw.dpy, xw.vis, xw.depth, ZPixmap, 0,
+ (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,
+ (char *)data, w, h, 32, w * 8);
+ #endif // ALPHA_PATCH
+ 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;
+ #if 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));
+ #endif // ALPHA_PATCH
+ 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);
+ }
+}
+\ No newline at end of file
diff --git a/patch/background_image_x.h b/patch/background_image_x.h
@@ -0,0 +1,5 @@
+#include <arpa/inet.h>
+
+static void updatexy(void);
+static XImage *loadff(const char *);
+static void bginit();
+\ No newline at end of file
diff --git a/patch/x_include.c b/patch/x_include.c
@@ -1,4 +1,7 @@
/* Patches */
+#if BACKGROUND_IMAGE_PATCH
+#include "background_image_x.c"
+#endif
#if BOXDRAW_PATCH
#include "boxdraw.c"
#endif
diff --git a/patch/x_include.h b/patch/x_include.h
@@ -1,4 +1,7 @@
/* Patches */
+#if BACKGROUND_IMAGE_PATCH
+#include "background_image_x.h"
+#endif
#if BOXDRAW_PATCH
#include "boxdraw.h"
#endif
diff --git a/patches.def.h b/patches.def.h
@@ -48,6 +48,12 @@
*/
#define ANYSIZE_SIMPLE_PATCH 0
+/* Draws a background image in farbfeld format in place of the defaultbg color allowing for pseudo
+ * transparency.
+ * https://st.suckless.org/patches/background_image/
+ */
+#define BACKGROUND_IMAGE_PATCH 0
+
/* This patch allows the use of a blinking cursor.
* Only cursor styles 0, 1, 3, 5, and 7 blink. Set cursorstyle accordingly.
* Cursor styles are defined here:
diff --git a/st.h b/st.h
@@ -181,6 +181,9 @@ typedef union {
typedef struct {
int tw, th; /* tty width and height */
int w, h; /* window width and height */
+ #if BACKGROUND_IMAGE_PATCH
+ int x, y; /* window location */
+ #endif // BACKGROUND_IMAGE_PATCH
#if ANYSIZE_PATCH
int hborderpx, vborderpx;
#endif // ANYSIZE_PATCH
@@ -210,6 +213,9 @@ typedef struct {
XVaNestedList spotlist;
} ime;
Draw draw;
+ #if BACKGROUND_IMAGE_PATCH
+ GC bggc; /* Graphics Context for background */
+ #endif // BACKGROUND_IMAGE_PATCH
Visual *vis;
XSetWindowAttributes attrs;
#if HIDECURSOR_PATCH
diff --git a/x.c b/x.c
@@ -548,6 +548,14 @@ propnotify(XEvent *e)
xpev->atom == clipboard)) {
selnotify(e);
}
+
+ #if BACKGROUND_IMAGE_PATCH
+ if (pseudotransparency &&
+ !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 13)) {
+ updatexy();
+ redraw();
+ }
+ #endif // BACKGROUND_IMAGE_PATCH
}
void
@@ -578,7 +586,12 @@ selnotify(XEvent *e)
return;
}
- if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
+ #if BACKGROUND_IMAGE_PATCH
+ if (e->type == PropertyNotify && nitems == 0 && rem == 0 && !pseudotransparency)
+ #else
+ if (e->type == PropertyNotify && nitems == 0 && rem == 0)
+ #endif // BACKGROUND_IMAGE_PATCH
+ {
/*
* If there is some PropertyNotify with no data, then
* this is the signal of the selection owner that all
@@ -596,9 +609,15 @@ selnotify(XEvent *e)
* when the selection owner does send us the next
* chunk of data.
*/
+ #if BACKGROUND_IMAGE_PATCH
+ if (!pseudotransparency) {
+ #endif // BACKGROUND_IMAGE_PATCH
MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
&xw.attrs);
+ #if BACKGROUND_IMAGE_PATCH
+ }
+ #endif // BACKGROUND_IMAGE_PATCH
/*
* Deleting the property is the transfer start signal.
@@ -997,7 +1016,11 @@ xsetcolorname(int x, const char *name)
void
xclear(int x1, int y1, int x2, int y2)
{
- #if INVERT_PATCH
+ #if BACKGROUND_IMAGE_PATCH
+ if (pseudotransparency)
+ XSetTSOrigin(xw.dpy, xw.bggc, -win.x, -win.y);
+ XFillRectangle(xw.dpy, xw.buf, xw.bggc, x1, y1, x2-x1, y2-y1);
+ #elif INVERT_PATCH
Color c;
c = dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg];
if (invertcolors) {
@@ -1911,6 +1934,11 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
#endif // ANYSIZE_PATCH
/* Clean up the region we want to draw to. */
+ #if BACKGROUND_IMAGE_PATCH
+ if (bg == &dc.col[defaultbg])
+ xclear(winx, winy, winx + width, winy + win.ch);
+ else
+ #endif // BACKGROUND_IMAGE_PATCH
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
#if WIDE_GLYPHS_PATCH
}
@@ -3094,6 +3122,15 @@ resize(XEvent *e)
XWindowChanges wc;
#endif // ST_EMBEDDER_PATCH
+ #if BACKGROUND_IMAGE_PATCH
+ 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
+ #endif // BACKGROUND_IMAGE_PATCH
if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
return;
@@ -3379,6 +3416,9 @@ run:
#endif // ALPHA_FOCUS_HIGHLIGHT_PATCH
tnew(cols, rows);
xinit(cols, rows);
+ #if BACKGROUND_IMAGE_PATCH
+ bginit();
+ #endif // BACKGROUND_IMAGE_PATCH
xsetenv();
selinit();
#if WORKINGDIR_PATCH