sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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