st-visualbell2-enhanced-2018-10-16-30ec9a3.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       st-visualbell2-enhanced-2018-10-16-30ec9a3.diff (8584B)
       ---
            1 From bcc850d57fb4cb6941008fb2808d4d0d373aa5f8 Mon Sep 17 00:00:00 2001
            2 From: "Avi Halachmi (:avih)" <avihpit@yahoo.com>
            3 Date: Mon, 15 Oct 2018 01:06:01 +0300
            4 Subject: [PATCH 1/2] [vbell2] add visual bell with two rendering modes
            5 
            6 - Inverse the whole terminal - "standard" visual-bell, a bit jarring.
            7 - Inverse outer (border) cells - much less jarring, yet plenty visible.
            8 
            9 Note: blink used a timeout of 1us after drawing, probably to
           10 re-calculate the timeout without being affected by draw speed. This was
           11 changed to 1ms for code simplicity, and should be inconsequential.
           12 ---
           13  config.def.h | 11 ++++++++
           14  st.c         |  1 -
           15  st.h         |  1 +
           16  x.c          | 77 +++++++++++++++++++++++++++++++++++++++-------------
           17  4 files changed, 70 insertions(+), 20 deletions(-)
           18 
           19 diff --git a/config.def.h b/config.def.h
           20 index 823e79f..0915ce5 100644
           21 --- a/config.def.h
           22 +++ b/config.def.h
           23 @@ -62,6 +62,17 @@ static unsigned int cursorthickness = 2;
           24   */
           25  static int bellvolume = 0;
           26  
           27 +/*
           28 + * visual-bell timeout (set to 0 to disable visual-bell).
           29 + */
           30 +static int vbelltimeout = 0;
           31 +/*
           32 + * visual bell mode when enabled:
           33 + *   1: Inverse whole screen
           34 + *   2: Inverse outer (border) cells
           35 + */
           36 +static int vbellmode = 1;
           37 +
           38  /* default TERM value */
           39  char *termname = "st-256color";
           40  
           41 diff --git a/st.c b/st.c
           42 index 46cf2da..1229479 100644
           43 --- a/st.c
           44 +++ b/st.c
           45 @@ -193,7 +193,6 @@ static void tsetscroll(int, int);
           46  static void tswapscreen(void);
           47  static void tsetmode(int, int, int *, int);
           48  static int twrite(const char *, int, int);
           49 -static void tfulldirt(void);
           50  static void tcontrolcode(uchar );
           51  static void tdectest(char );
           52  static void tdefutf8(char);
           53 diff --git a/st.h b/st.h
           54 index 38c61c4..619d716 100644
           55 --- a/st.h
           56 +++ b/st.h
           57 @@ -89,6 +89,7 @@ int tattrset(int);
           58  void tnew(int, int);
           59  void tresize(int, int);
           60  void tsetdirtattr(int);
           61 +void tfulldirt();
           62  void ttyhangup(void);
           63  int ttynew(char *, char *, char *, char **);
           64  size_t ttyread(void);
           65 diff --git a/x.c b/x.c
           66 index 00cb6b1..7e66c6d 100644
           67 --- a/x.c
           68 +++ b/x.c
           69 @@ -82,6 +82,8 @@ typedef struct {
           70          int cw; /* char width  */
           71          int mode; /* window state/mode flags */
           72          int cursor; /* cursor style */
           73 +        int vbellset; /* 1 during visual bell, 0 otherwise */
           74 +        struct timespec lastvbell;
           75  } TermWindow;
           76  
           77  typedef struct {
           78 @@ -173,6 +175,9 @@ static void mousereport(XEvent *);
           79  static char *kmap(KeySym, uint);
           80  static int match(uint, uint);
           81  
           82 +static void vbellbegin();
           83 +static int isvbellcell(int x, int y);
           84 +
           85  static void run(void);
           86  static void usage(void);
           87  
           88 @@ -1528,6 +1533,8 @@ xdrawline(Line line, int x1, int y1, int x2)
           89                          continue;
           90                  if (selected(x, y1))
           91                          new.mode ^= ATTR_REVERSE;
           92 +                if (win.vbellset && isvbellcell(x, y1))
           93 +                        new.mode ^= ATTR_REVERSE;
           94                  if (i > 0 && ATTRCMP(base, new)) {
           95                          xdrawglyphfontspecs(specs, base, i, ox, y1);
           96                          specs += i;
           97 @@ -1610,6 +1617,28 @@ xseturgency(int add)
           98          XFree(h);
           99  }
          100  
          101 +int
          102 +isvbellcell(int x, int y)
          103 +{
          104 +        if (vbellmode == 1)
          105 +                return 1;
          106 +        if (vbellmode == 2)
          107 +                return y == 0 || y == win.th / win.ch - 1 ||
          108 +                       x == 0 || x == win.tw / win.cw - 1;
          109 +        return 0;
          110 +}
          111 +
          112 +void
          113 +vbellbegin() {
          114 +        clock_gettime(CLOCK_MONOTONIC, &win.lastvbell);
          115 +        if (win.vbellset) /* already visible, just extend win.lastvbell */
          116 +                return;
          117 +        win.vbellset = 1;
          118 +        tfulldirt();
          119 +        draw();
          120 +        XFlush(xw.dpy);
          121 +}
          122 +
          123  void
          124  xbell(void)
          125  {
          126 @@ -1617,6 +1646,8 @@ xbell(void)
          127                  xseturgency(1);
          128          if (bellvolume)
          129                  XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
          130 +        if (vbelltimeout)
          131 +                vbellbegin();
          132  }
          133  
          134  void
          135 @@ -1770,7 +1801,7 @@ run(void)
          136          int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
          137          int ttyfd;
          138          struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
          139 -        long deltatime;
          140 +        long deltatime, to_ms, remain;
          141  
          142          /* Waiting for window mapping */
          143          do {
          144 @@ -1822,11 +1853,28 @@ run(void)
          145                  tv = &drawtimeout;
          146  
          147                  dodraw = 0;
          148 -                if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
          149 -                        tsetdirtattr(ATTR_BLINK);
          150 -                        win.mode ^= MODE_BLINK;
          151 -                        lastblink = now;
          152 -                        dodraw = 1;
          153 +                to_ms = -1; /* timeout in ms, indefinite if negative */
          154 +                if (blinkset) {
          155 +                        remain = blinktimeout - TIMEDIFF(now, lastblink);
          156 +                        if (remain <= 0) {
          157 +                                dodraw = 1;
          158 +                                remain = 1; /* draw, wait 1ms, and re-calc */
          159 +                                tsetdirtattr(ATTR_BLINK);
          160 +                                win.mode ^= MODE_BLINK;
          161 +                                lastblink = now;
          162 +                        }
          163 +                        to_ms = remain;
          164 +                }
          165 +                if (win.vbellset) {
          166 +                        remain = vbelltimeout - TIMEDIFF(now, win.lastvbell);
          167 +                        if (remain <= 0) {
          168 +                                dodraw = 1;
          169 +                                remain = -1; /* draw (clear), and that's it */
          170 +                                tfulldirt();
          171 +                                win.vbellset = 0;
          172 +                        }
          173 +                        if (remain >= 0 && (to_ms < 0 || remain < to_ms))
          174 +                                to_ms = remain;
          175                  }
          176                  deltatime = TIMEDIFF(now, last);
          177                  if (deltatime > 1000 / (xev ? xfps : actionfps)) {
          178 @@ -1849,19 +1897,10 @@ run(void)
          179                          if (xev && !FD_ISSET(xfd, &rfd))
          180                                  xev--;
          181                          if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) {
          182 -                                if (blinkset) {
          183 -                                        if (TIMEDIFF(now, lastblink) \
          184 -                                                        > blinktimeout) {
          185 -                                                drawtimeout.tv_nsec = 1000;
          186 -                                        } else {
          187 -                                                drawtimeout.tv_nsec = (1E6 * \
          188 -                                                        (blinktimeout - \
          189 -                                                        TIMEDIFF(now,
          190 -                                                                lastblink)));
          191 -                                        }
          192 -                                        drawtimeout.tv_sec = \
          193 -                                            drawtimeout.tv_nsec / 1E9;
          194 -                                        drawtimeout.tv_nsec %= (long)1E9;
          195 +                                if (to_ms >= 0) {
          196 +                                        static const long k = 1E3, m = 1E6;
          197 +                                        drawtimeout.tv_sec = to_ms / k;
          198 +                                        drawtimeout.tv_nsec = (to_ms % k) * m;
          199                                  } else {
          200                                          tv = NULL;
          201                                  }
          202 -- 
          203 2.19.1
          204 
          205 
          206 From 587d0fdcdcccb601f61de4f6186ae310c8adb0e3 Mon Sep 17 00:00:00 2001
          207 From: "Avi Halachmi (:avih)" <avihpit@yahoo.com>
          208 Date: Tue, 16 Oct 2018 16:04:45 +0300
          209 Subject: [PATCH 2/2] [vbell2] visual bell: experimental circle rendering mode
          210 
          211 This commit experiments with alternative rendering of visual bell,
          212 and as such it's extensively/excessively configurable.
          213 
          214 It renders an overlay of a circle with configurable colors (base,
          215 outline), position and size. Defaults to the center of the window.
          216 
          217 Size can be relative to window or chars width, and allows for instance
          218 to place it at the middle/side of a top/bottom tmux status-bar with
          219 exact char height to make it look like a flashing LED at the bar, etc.
          220 ---
          221  config.def.h | 12 ++++++++++++
          222  x.c          | 24 +++++++++++++++++++++++-
          223  2 files changed, 35 insertions(+), 1 deletion(-)
          224 
          225 diff --git a/config.def.h b/config.def.h
          226 index 0915ce5..a1c7f24 100644
          227 --- a/config.def.h
          228 +++ b/config.def.h
          229 @@ -70,8 +70,20 @@ static int vbelltimeout = 0;
          230   * visual bell mode when enabled:
          231   *   1: Inverse whole screen
          232   *   2: Inverse outer (border) cells
          233 + *   3: Draw a filled circle.
          234   */
          235  static int vbellmode = 1;
          236 +/*
          237 + * for vbellmode == 3 (circle) the following parameters apply:
          238 + * - base and outline colors (colorname index - see below).
          239 + * - radius: relative to window width, or if negative: relative to cell-width.
          240 + * - position: relative to window width/height (0 and 1 are at the edges).
          241 + */
          242 +static int vbellcolor = 3;
          243 +static int vbellcolor_outline = 1;
          244 +static float vbellradius = 0.03;
          245 +static float vbellx = 0.5;
          246 +static float vbelly = 0.5;
          247  
          248  /* default TERM value */
          249  char *termname = "st-256color";
          250 diff --git a/x.c b/x.c
          251 index 7e66c6d..eb895d4 100644
          252 --- a/x.c
          253 +++ b/x.c
          254 @@ -177,6 +177,8 @@ static int match(uint, uint);
          255  
          256  static void vbellbegin();
          257  static int isvbellcell(int x, int y);
          258 +static void xdrawvbell();
          259 +static void xfillcircle(int x, int y, int r, uint color_ix);
          260  
          261  static void run(void);
          262  static void usage(void);
          263 @@ -1554,6 +1556,9 @@ xdrawline(Line line, int x1, int y1, int x2)
          264  void
          265  xfinishdraw(void)
          266  {
          267 +        if (vbellmode == 3 && win.vbellset)
          268 +                xdrawvbell();
          269 +
          270          XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
          271                          win.h, 0, 0);
          272          XSetForeground(xw.dpy, dc.gc,
          273 @@ -1617,6 +1622,22 @@ xseturgency(int add)
          274          XFree(h);
          275  }
          276  
          277 +void
          278 +xfillcircle(int x, int y, int r, uint color_ix)
          279 +{
          280 +        XSetForeground(xw.dpy, dc.gc, dc.col[color_ix].pixel);
          281 +        XFillArc(xw.dpy, xw.buf, dc.gc, x - r, y - r, r * 2, r * 2, 0, 360*64);
          282 +}
          283 +
          284 +void
          285 +xdrawvbell() {
          286 +        int r = round(vbellradius * (vbellradius > 0 ? win.w : -win.cw));
          287 +        int x = borderpx + r + vbellx * (win.tw - 2 * r);
          288 +        int y = borderpx + r + vbelly * (win.th - 2 * r);
          289 +        xfillcircle(x, y, r, vbellcolor_outline);
          290 +        xfillcircle(x, y, r / 1.2, vbellcolor); /* 1.2 - an artistic choice */
          291 +}
          292 +
          293  int
          294  isvbellcell(int x, int y)
          295  {
          296 @@ -1634,7 +1655,8 @@ vbellbegin() {
          297          if (win.vbellset) /* already visible, just extend win.lastvbell */
          298                  return;
          299          win.vbellset = 1;
          300 -        tfulldirt();
          301 +        if (vbellmode != 3) /* 3 is an overlay, no need to re-render cells */
          302 +                tfulldirt();
          303          draw();
          304          XFlush(xw.dpy);
          305  }
          306 -- 
          307 2.19.1
          308