sites

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

st-background-image-0.8.5.diff (7079B)


      1 From 4ce17bbc340ca1f93f9be686f4a796797f9ca6d5 Mon Sep 17 00:00:00 2001
      2 From: Matthias Schoth <mschoth@gmail.com>
      3 Date: Sat, 16 Apr 2022 14:21:22 +0200
      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 91ab8ca..ad19e3d 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 8a16faa..fedef53 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 @@ -504,6 +510,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 @@ -534,7 +546,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 @@ -552,9 +565,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 @@ -835,9 +850,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 @@ -1223,6 +1238,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, "Can not open background image file\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\n");
    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\n");
    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 @@ -1463,7 +1572,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 @@ -1886,9 +1998,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 @@ -2072,6 +2192,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