st-background-image-0.8.4.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       st-background-image-0.8.4.diff (7073B)
       ---
            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