first
[dcc-suckless-config] / based-simple-term / patches / st-background-image-0.8.4.diff
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