commit 94179be8705998ab15098ecc3588f9ab335f2f67
Author: Matthias Schoth <[email protected]>
Date:   Sun Apr 17 04:11:30 2022 +0200

    [st][patch][background_image] update and signal reloading
    - update patch to version 0.8.5
    - add reloading of background image on USR1 signal as option

diff --git a/st.suckless.org/patches/background_image/index.md 
b/st.suckless.org/patches/background_image/index.md
index 49c88c63..7db9f608 100644
--- a/st.suckless.org/patches/background_image/index.md
+++ b/st.suckless.org/patches/background_image/index.md
@@ -32,7 +32,29 @@ invoked with the following command:
 
 Download
 --------
+
 * [st-background-image-0.8.4.diff](st-background-image-0.8.4.diff)
+* [st-background-image-0.8.5.diff](st-background-image-0.8.5.diff)
+
+Signal Reloading
+----------------
+
+Apply the following patch on top of the previous to enable reloading the
+background image when a USR1 signal occurs:
+
+* 
[st-background-image-signal-reload-0.8.5.diff](st-background-image-signal-reload-0.8.5.diff)
+
+If you use the [xresources with signal 
reloading](//st.suckless.org/patches/xresources-with-reload-signal)
+patch ignore the patch above and simply add these two lines to the beginning of
+the `reload` function located in the file `x.c`:
+
+       XFreeGC(xw.dpy, xw.bggc);
+       bginit();
+
+*Hint*: You can send a USR1 signal to all st processes with the following
+command:
+
+       pidof st | xargs kill -s USR1
 
 Authors
 -------
diff --git 
a/st.suckless.org/patches/background_image/st-background-image-0.8.5.diff 
b/st.suckless.org/patches/background_image/st-background-image-0.8.5.diff
new file mode 100644
index 00000000..9f6c5495
--- /dev/null
+++ b/st.suckless.org/patches/background_image/st-background-image-0.8.5.diff
@@ -0,0 +1,262 @@
+From 4ce17bbc340ca1f93f9be686f4a796797f9ca6d5 Mon Sep 17 00:00:00 2001
+From: Matthias Schoth <[email protected]>
+Date: Sat, 16 Apr 2022 14:21:22 +0200
+Subject: [PATCH] Implements background image and pseudo transparancy support.
+
+---
+ config.def.h |   8 +++
+ x.c          | 141 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 139 insertions(+), 10 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 91ab8ca..ad19e3d 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -8,6 +8,14 @@
+ static char *font = "Liberation 
Mono:pixelsize=12:antialias=true:autohint=true";
+ static int borderpx = 2;
+ 
++/*
++ * 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;
++
+ /*
+  * What program is execed by st depends of these precedence rules:
+  * 1: program passed with -e
+diff --git a/x.c b/x.c
+index 8a16faa..fedef53 100644
+--- a/x.c
++++ b/x.c
+@@ -14,6 +14,7 @@
+ #include <X11/keysym.h>
+ #include <X11/Xft/Xft.h>
+ #include <X11/XKBlib.h>
++#include <arpa/inet.h>
+ 
+ char *argv0;
+ #include "arg.h"
+@@ -81,6 +82,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
+ typedef struct {
+       int tw, th; /* tty width and height */
+       int w, h; /* window width and height */
++      int x, y; /* window location */
+       int ch; /* char height */
+       int cw; /* char width  */
+       int mode; /* window state/mode flags */
+@@ -101,6 +103,7 @@ typedef struct {
+               XVaNestedList spotlist;
+       } ime;
+       Draw draw;
++      GC bggc;          /* Graphics Context for background */
+       Visual *vis;
+       XSetWindowAttributes attrs;
+       int scr;
+@@ -151,6 +154,9 @@ static void ximinstantiate(Display *, XPointer, XPointer);
+ static void ximdestroy(XIM, XPointer, XPointer);
+ static int xicdestroy(XIC, XPointer, XPointer);
+ static void xinit(int, int);
++static void updatexy(void);
++static XImage *loadff(const char *);
++static void bginit();
+ static void cresize(int, int);
+ static void xresize(int, int);
+ static void xhints(void);
+@@ -504,6 +510,12 @@ propnotify(XEvent *e)
+                        xpev->atom == clipboard)) {
+               selnotify(e);
+       }
++
++      if (pseudotransparency &&
++          !strncmp(XGetAtomName(xw.dpy, e->xproperty.atom), "_NET_WM_STATE", 
13)) {
++              updatexy();
++              redraw();
++      }
+ }
+ 
+ void
+@@ -534,7 +546,8 @@ selnotify(XEvent *e)
+                       return;
+               }
+ 
+-              if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
++              if (e->type == PropertyNotify && nitems == 0 && rem == 0 &&
++                  !pseudotransparency) {
+                       /*
+                        * If there is some PropertyNotify with no data, then
+                        * this is the signal of the selection owner that all
+@@ -552,9 +565,11 @@ selnotify(XEvent *e)
+                        * when the selection owner does send us the next
+                        * chunk of data.
+                        */
+-                      MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
+-                      XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
++                      if (!pseudotransparency) {
++                              MODBIT(xw.attrs.event_mask, 1, 
PropertyChangeMask);
++                              XChangeWindowAttributes(xw.dpy, xw.win, 
CWEventMask,
+                                       &xw.attrs);
++                      }
+ 
+                       /*
+                        * Deleting the property is the transfer start signal.
+@@ -835,9 +850,9 @@ xsetcolorname(int x, const char *name)
+ void
+ xclear(int x1, int y1, int x2, int y2)
+ {
+-      XftDrawRect(xw.draw,
+-                      &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg],
+-                      x1, y1, x2-x1, y2-y1);
++      if (pseudotransparency)
++              XSetTSOrigin(xw.dpy, xw.bggc, -win.x, -win.y);
++      XFillRectangle(xw.dpy, xw.buf, xw.bggc, x1, y1, x2-x1, y2-y1);
+ }
+ 
+ void
+@@ -1223,6 +1238,100 @@ xinit(int cols, int rows)
+               xsel.xtarget = XA_STRING;
+ }
+ 
++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, "Can not open background image file
");
++              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
");
++                      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;
++
++      XImage *xi = XCreateImage(xw.dpy, DefaultVisual(xw.dpy, xw.scr),
++                                  DefaultDepth(xw.dpy, xw.scr), ZPixmap, 0,
++                                  (char *)data, w, h, 32, w * 8);
++      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;
++      bgimg = XCreatePixmap(xw.dpy, xw.win, bgxi->width, bgxi->height,
++                            DefaultDepth(xw.dpy, xw.scr));
++      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);
++      }
++}
++
+ int
+ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
+ {
+@@ -1463,7 +1572,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, 
Glyph base, int len, int x, i
+               xclear(winx, winy + win.ch, winx + width, win.h);
+ 
+       /* Clean up the region we want to draw to. */
+-      XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
++      if (bg == &dc.col[defaultbg])
++              xclear(winx, winy, winx + width, winy + win.ch);
++      else
++              XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
+ 
+       /* Set the clip region because Xft is sometimes dirty. */
+       r.x = 0;
+@@ -1886,9 +1998,17 @@ cmessage(XEvent *e)
+ void
+ resize(XEvent *e)
+ {
+-      if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
+-              return;
+-
++      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 {
++              if (e->xconfigure.width == win.w &&
++                  e->xconfigure.height == win.h)
++                      return;
++      }
+       cresize(e->xconfigure.width, e->xconfigure.height);
+ }
+ 
+@@ -2072,6 +2192,7 @@ run:
+       rows = MAX(rows, 1);
+       tnew(cols, rows);
+       xinit(cols, rows);
++      bginit();
+       xsetenv();
+       selinit();
+       run();
+-- 
+2.35.1
+
diff --git 
a/st.suckless.org/patches/background_image/st-background-image-signal-reload-0.8.5.diff
 
b/st.suckless.org/patches/background_image/st-background-image-signal-reload-0.8.5.diff
new file mode 100644
index 00000000..d323efc9
--- /dev/null
+++ 
b/st.suckless.org/patches/background_image/st-background-image-signal-reload-0.8.5.diff
@@ -0,0 +1,51 @@
+From 1317d64817460aee9321e29e5e31c072d59139c6 Mon Sep 17 00:00:00 2001
+From: Matthias Schoth <[email protected]>
+Date: Sun, 17 Apr 2022 04:01:59 +0200
+Subject: [PATCH] Reload background image on USR1 signal.
+
+---
+ x.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/x.c b/x.c
+index fedef53..ac79ac7 100644
+--- a/x.c
++++ b/x.c
+@@ -156,6 +156,7 @@ static int xicdestroy(XIC, XPointer, XPointer);
+ static void xinit(int, int);
+ static void updatexy(void);
+ static XImage *loadff(const char *);
++static void bgreload();
+ static void bginit();
+ static void cresize(int, int);
+ static void xresize(int, int);
+@@ -1305,6 +1306,18 @@ loadff(const char *filename)
+       return xi;
+ }
+ 
++/*
++ * reload background image on USR1 signal
++ */
++void
++bgreload()
++{
++      XFreeGC(xw.dpy, xw.bggc);
++      bginit();
++      redraw();
++      signal(SIGUSR1, bgreload);
++}
++
+ /*
+  * initialize background image
+  */
+@@ -2193,6 +2206,7 @@ run:
+       tnew(cols, rows);
+       xinit(cols, rows);
+       bginit();
++      signal(SIGUSR1, bgreload);
+       xsetenv();
+       selinit();
+       run();
+-- 
+2.35.3
+


Reply via email to