sites

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

commit 3a82e2aa63c17fb10dfdb98803668ef50cfcd15f
parent c2ae8c48dede4c3c1398512aa1320231e131eb46
Author: Avi Halachmi (:avih) <avihpit@yahoo.com>
Date:   Tue, 16 Oct 2018 23:27:31 +0300

[st][patch] add another visual-bell implementation

Diffstat:
st.suckless.org/patches/visualbell/index.md | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
st.suckless.org/patches/visualbell/st-visualbell2-basic-2018-10-16-30ec9a3.patch | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
st.suckless.org/patches/visualbell/st-visualbell2-enhanced-2018-10-16-30ec9a3.patch | 308+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 567 insertions(+), 0 deletions(-)

diff --git a/st.suckless.org/patches/visualbell/index.md b/st.suckless.org/patches/visualbell/index.md @@ -1,6 +1,12 @@ visualbell ========== +This page contains two unrelated implementations of visual bell which are not +compatible with eachother. If you have one of them applied, remove it before +trying the other. + +# === Visual bell 1 === + Description ----------- @@ -26,3 +32,52 @@ Authors * Matthias Schoth - <mschoth@gmail.com> * Laslo Hunhold - <dev@frign.de> (git port) * Alexis Ben Miloud--Josselin; panpo; alexisbmj+code at protonmail dot com. + +# === Visual bell 2 === + +Description +----------- + +Briefly renders a configurable visual indication on terminal bell event. + +Notes +----- + +- There are two variants available for download: basic and enhanced. +- The enhanced version file already includes the basic version in it, and + supports the basic options too. +- Both variants can be applied with either `git am <patch-file>` or + ` patch -p1 < <patch-file>`. +- Visual bell is disabled by default, and can be enabled/configured via + `config.h`. If you already have this file, you'll need to add the visual-bell + values by copying them from `config.def.h` - which also includes their docs. + +### The basic variant supports: + +- Invert the whole screen (default). +- Invert only the outer (border) cells for a less jarring effect. +- Configuring the flash duration (default: 100ms). + +### The enhanced variant: + +This version experiments with a more graphical indication, by adding support +for rendering a filled circle (needs to be chosen at `config.h`), which can be +configured for: + +- Position: any corner/edge, center of the screen, or anything in between. +- Size: relative to the window width or to the cell width. +- Colors: base and outline. + +The enhanced variant allows, for instance, to render what looks like a LED +indicator at a tmux status bar, with correct cell height, and can be +positioned at the side/middle of a top/bottom bar, etc. + +Download +-------- + +- [st-visualbell2-basic-2018-10-16-30ec9a3.patch](st-visualbell2-basic-2018-10-16-30ec9a3.patch) +- [st-visualbell2-enhanced-2018-10-16-30ec9a3.patch](st-visualbell2-enhanced-2018-10-16-30ec9a3.patch) + +Author +------ +- Avi Halachmi (:avih) - [https://github.com/avih](https://github.com/avih) diff --git a/st.suckless.org/patches/visualbell/st-visualbell2-basic-2018-10-16-30ec9a3.patch b/st.suckless.org/patches/visualbell/st-visualbell2-basic-2018-10-16-30ec9a3.patch @@ -0,0 +1,204 @@ +From bcc850d57fb4cb6941008fb2808d4d0d373aa5f8 Mon Sep 17 00:00:00 2001 +From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> +Date: Mon, 15 Oct 2018 01:06:01 +0300 +Subject: [PATCH] [vbell2] add visual bell with two rendering modes + +- Inverse the whole terminal - "standard" visual-bell, a bit jarring. +- Inverse outer (border) cells - much less jarring, yet plenty visible. + +Note: blink used a timeout of 1us after drawing, probably to +re-calculate the timeout without being affected by draw speed. This was +changed to 1ms for code simplicity, and should be inconsequential. +--- + config.def.h | 11 ++++++++ + st.c | 1 - + st.h | 1 + + x.c | 77 +++++++++++++++++++++++++++++++++++++++------------- + 4 files changed, 70 insertions(+), 20 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 823e79f..0915ce5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -62,6 +62,17 @@ static unsigned int cursorthickness = 2; + */ + static int bellvolume = 0; + ++/* ++ * visual-bell timeout (set to 0 to disable visual-bell). ++ */ ++static int vbelltimeout = 0; ++/* ++ * visual bell mode when enabled: ++ * 1: Inverse whole screen ++ * 2: Inverse outer (border) cells ++ */ ++static int vbellmode = 1; ++ + /* default TERM value */ + char *termname = "st-256color"; + +diff --git a/st.c b/st.c +index 46cf2da..1229479 100644 +--- a/st.c ++++ b/st.c +@@ -193,7 +193,6 @@ static void tsetscroll(int, int); + static void tswapscreen(void); + static void tsetmode(int, int, int *, int); + static int twrite(const char *, int, int); +-static void tfulldirt(void); + static void tcontrolcode(uchar ); + static void tdectest(char ); + static void tdefutf8(char); +diff --git a/st.h b/st.h +index 38c61c4..619d716 100644 +--- a/st.h ++++ b/st.h +@@ -89,6 +89,7 @@ int tattrset(int); + void tnew(int, int); + void tresize(int, int); + void tsetdirtattr(int); ++void tfulldirt(); + void ttyhangup(void); + int ttynew(char *, char *, char *, char **); + size_t ttyread(void); +diff --git a/x.c b/x.c +index 00cb6b1..7e66c6d 100644 +--- a/x.c ++++ b/x.c +@@ -82,6 +82,8 @@ typedef struct { + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ ++ int vbellset; /* 1 during visual bell, 0 otherwise */ ++ struct timespec lastvbell; + } TermWindow; + + typedef struct { +@@ -173,6 +175,9 @@ static void mousereport(XEvent *); + static char *kmap(KeySym, uint); + static int match(uint, uint); + ++static void vbellbegin(); ++static int isvbellcell(int x, int y); ++ + static void run(void); + static void usage(void); + +@@ -1528,6 +1533,8 @@ xdrawline(Line line, int x1, int y1, int x2) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; ++ if (win.vbellset && isvbellcell(x, y1)) ++ new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; +@@ -1610,6 +1617,28 @@ xseturgency(int add) + XFree(h); + } + ++int ++isvbellcell(int x, int y) ++{ ++ if (vbellmode == 1) ++ return 1; ++ if (vbellmode == 2) ++ return y == 0 || y == win.th / win.ch - 1 || ++ x == 0 || x == win.tw / win.cw - 1; ++ return 0; ++} ++ ++void ++vbellbegin() { ++ clock_gettime(CLOCK_MONOTONIC, &win.lastvbell); ++ if (win.vbellset) /* already visible, just extend win.lastvbell */ ++ return; ++ win.vbellset = 1; ++ tfulldirt(); ++ draw(); ++ XFlush(xw.dpy); ++} ++ + void + xbell(void) + { +@@ -1617,6 +1646,8 @@ xbell(void) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); ++ if (vbelltimeout) ++ vbellbegin(); + } + + void +@@ -1770,7 +1801,7 @@ run(void) + int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0; + int ttyfd; + struct timespec drawtimeout, *tv = NULL, now, last, lastblink; +- long deltatime; ++ long deltatime, to_ms, remain; + + /* Waiting for window mapping */ + do { +@@ -1822,11 +1853,28 @@ run(void) + tv = &drawtimeout; + + dodraw = 0; +- if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { +- tsetdirtattr(ATTR_BLINK); +- win.mode ^= MODE_BLINK; +- lastblink = now; +- dodraw = 1; ++ to_ms = -1; /* timeout in ms, indefinite if negative */ ++ if (blinkset) { ++ remain = blinktimeout - TIMEDIFF(now, lastblink); ++ if (remain <= 0) { ++ dodraw = 1; ++ remain = 1; /* draw, wait 1ms, and re-calc */ ++ tsetdirtattr(ATTR_BLINK); ++ win.mode ^= MODE_BLINK; ++ lastblink = now; ++ } ++ to_ms = remain; ++ } ++ if (win.vbellset) { ++ remain = vbelltimeout - TIMEDIFF(now, win.lastvbell); ++ if (remain <= 0) { ++ dodraw = 1; ++ remain = -1; /* draw (clear), and that's it */ ++ tfulldirt(); ++ win.vbellset = 0; ++ } ++ if (remain >= 0 && (to_ms < 0 || remain < to_ms)) ++ to_ms = remain; + } + deltatime = TIMEDIFF(now, last); + if (deltatime > 1000 / (xev ? xfps : actionfps)) { +@@ -1849,19 +1897,10 @@ run(void) + if (xev && !FD_ISSET(xfd, &rfd)) + xev--; + if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) { +- if (blinkset) { +- if (TIMEDIFF(now, lastblink) \ +- > blinktimeout) { +- drawtimeout.tv_nsec = 1000; +- } else { +- drawtimeout.tv_nsec = (1E6 * \ +- (blinktimeout - \ +- TIMEDIFF(now, +- lastblink))); +- } +- drawtimeout.tv_sec = \ +- drawtimeout.tv_nsec / 1E9; +- drawtimeout.tv_nsec %= (long)1E9; ++ if (to_ms >= 0) { ++ static const long k = 1E3, m = 1E6; ++ drawtimeout.tv_sec = to_ms / k; ++ drawtimeout.tv_nsec = (to_ms % k) * m; + } else { + tv = NULL; + } +-- +2.19.1 + diff --git a/st.suckless.org/patches/visualbell/st-visualbell2-enhanced-2018-10-16-30ec9a3.patch b/st.suckless.org/patches/visualbell/st-visualbell2-enhanced-2018-10-16-30ec9a3.patch @@ -0,0 +1,308 @@ +From bcc850d57fb4cb6941008fb2808d4d0d373aa5f8 Mon Sep 17 00:00:00 2001 +From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> +Date: Mon, 15 Oct 2018 01:06:01 +0300 +Subject: [PATCH 1/2] [vbell2] add visual bell with two rendering modes + +- Inverse the whole terminal - "standard" visual-bell, a bit jarring. +- Inverse outer (border) cells - much less jarring, yet plenty visible. + +Note: blink used a timeout of 1us after drawing, probably to +re-calculate the timeout without being affected by draw speed. This was +changed to 1ms for code simplicity, and should be inconsequential. +--- + config.def.h | 11 ++++++++ + st.c | 1 - + st.h | 1 + + x.c | 77 +++++++++++++++++++++++++++++++++++++++------------- + 4 files changed, 70 insertions(+), 20 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 823e79f..0915ce5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -62,6 +62,17 @@ static unsigned int cursorthickness = 2; + */ + static int bellvolume = 0; + ++/* ++ * visual-bell timeout (set to 0 to disable visual-bell). ++ */ ++static int vbelltimeout = 0; ++/* ++ * visual bell mode when enabled: ++ * 1: Inverse whole screen ++ * 2: Inverse outer (border) cells ++ */ ++static int vbellmode = 1; ++ + /* default TERM value */ + char *termname = "st-256color"; + +diff --git a/st.c b/st.c +index 46cf2da..1229479 100644 +--- a/st.c ++++ b/st.c +@@ -193,7 +193,6 @@ static void tsetscroll(int, int); + static void tswapscreen(void); + static void tsetmode(int, int, int *, int); + static int twrite(const char *, int, int); +-static void tfulldirt(void); + static void tcontrolcode(uchar ); + static void tdectest(char ); + static void tdefutf8(char); +diff --git a/st.h b/st.h +index 38c61c4..619d716 100644 +--- a/st.h ++++ b/st.h +@@ -89,6 +89,7 @@ int tattrset(int); + void tnew(int, int); + void tresize(int, int); + void tsetdirtattr(int); ++void tfulldirt(); + void ttyhangup(void); + int ttynew(char *, char *, char *, char **); + size_t ttyread(void); +diff --git a/x.c b/x.c +index 00cb6b1..7e66c6d 100644 +--- a/x.c ++++ b/x.c +@@ -82,6 +82,8 @@ typedef struct { + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ ++ int vbellset; /* 1 during visual bell, 0 otherwise */ ++ struct timespec lastvbell; + } TermWindow; + + typedef struct { +@@ -173,6 +175,9 @@ static void mousereport(XEvent *); + static char *kmap(KeySym, uint); + static int match(uint, uint); + ++static void vbellbegin(); ++static int isvbellcell(int x, int y); ++ + static void run(void); + static void usage(void); + +@@ -1528,6 +1533,8 @@ xdrawline(Line line, int x1, int y1, int x2) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; ++ if (win.vbellset && isvbellcell(x, y1)) ++ new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; +@@ -1610,6 +1617,28 @@ xseturgency(int add) + XFree(h); + } + ++int ++isvbellcell(int x, int y) ++{ ++ if (vbellmode == 1) ++ return 1; ++ if (vbellmode == 2) ++ return y == 0 || y == win.th / win.ch - 1 || ++ x == 0 || x == win.tw / win.cw - 1; ++ return 0; ++} ++ ++void ++vbellbegin() { ++ clock_gettime(CLOCK_MONOTONIC, &win.lastvbell); ++ if (win.vbellset) /* already visible, just extend win.lastvbell */ ++ return; ++ win.vbellset = 1; ++ tfulldirt(); ++ draw(); ++ XFlush(xw.dpy); ++} ++ + void + xbell(void) + { +@@ -1617,6 +1646,8 @@ xbell(void) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); ++ if (vbelltimeout) ++ vbellbegin(); + } + + void +@@ -1770,7 +1801,7 @@ run(void) + int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0; + int ttyfd; + struct timespec drawtimeout, *tv = NULL, now, last, lastblink; +- long deltatime; ++ long deltatime, to_ms, remain; + + /* Waiting for window mapping */ + do { +@@ -1822,11 +1853,28 @@ run(void) + tv = &drawtimeout; + + dodraw = 0; +- if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { +- tsetdirtattr(ATTR_BLINK); +- win.mode ^= MODE_BLINK; +- lastblink = now; +- dodraw = 1; ++ to_ms = -1; /* timeout in ms, indefinite if negative */ ++ if (blinkset) { ++ remain = blinktimeout - TIMEDIFF(now, lastblink); ++ if (remain <= 0) { ++ dodraw = 1; ++ remain = 1; /* draw, wait 1ms, and re-calc */ ++ tsetdirtattr(ATTR_BLINK); ++ win.mode ^= MODE_BLINK; ++ lastblink = now; ++ } ++ to_ms = remain; ++ } ++ if (win.vbellset) { ++ remain = vbelltimeout - TIMEDIFF(now, win.lastvbell); ++ if (remain <= 0) { ++ dodraw = 1; ++ remain = -1; /* draw (clear), and that's it */ ++ tfulldirt(); ++ win.vbellset = 0; ++ } ++ if (remain >= 0 && (to_ms < 0 || remain < to_ms)) ++ to_ms = remain; + } + deltatime = TIMEDIFF(now, last); + if (deltatime > 1000 / (xev ? xfps : actionfps)) { +@@ -1849,19 +1897,10 @@ run(void) + if (xev && !FD_ISSET(xfd, &rfd)) + xev--; + if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) { +- if (blinkset) { +- if (TIMEDIFF(now, lastblink) \ +- > blinktimeout) { +- drawtimeout.tv_nsec = 1000; +- } else { +- drawtimeout.tv_nsec = (1E6 * \ +- (blinktimeout - \ +- TIMEDIFF(now, +- lastblink))); +- } +- drawtimeout.tv_sec = \ +- drawtimeout.tv_nsec / 1E9; +- drawtimeout.tv_nsec %= (long)1E9; ++ if (to_ms >= 0) { ++ static const long k = 1E3, m = 1E6; ++ drawtimeout.tv_sec = to_ms / k; ++ drawtimeout.tv_nsec = (to_ms % k) * m; + } else { + tv = NULL; + } +-- +2.19.1 + + +From 587d0fdcdcccb601f61de4f6186ae310c8adb0e3 Mon Sep 17 00:00:00 2001 +From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> +Date: Tue, 16 Oct 2018 16:04:45 +0300 +Subject: [PATCH 2/2] [vbell2] visual bell: experimental circle rendering mode + +This commit experiments with alternative rendering of visual bell, +and as such it's extensively/excessively configurable. + +It renders an overlay of a circle with configurable colors (base, +outline), position and size. Defaults to the center of the window. + +Size can be relative to window or chars width, and allows for instance +to place it at the middle/side of a top/bottom tmux status-bar with +exact char height to make it look like a flashing LED at the bar, etc. +--- + config.def.h | 12 ++++++++++++ + x.c | 24 +++++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 0915ce5..a1c7f24 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -70,8 +70,20 @@ static int vbelltimeout = 0; + * visual bell mode when enabled: + * 1: Inverse whole screen + * 2: Inverse outer (border) cells ++ * 3: Draw a filled circle. + */ + static int vbellmode = 1; ++/* ++ * for vbellmode == 3 (circle) the following parameters apply: ++ * - base and outline colors (colorname index - see below). ++ * - radius: relative to window width, or if negative: relative to cell-width. ++ * - position: relative to window width/height (0 and 1 are at the edges). ++ */ ++static int vbellcolor = 3; ++static int vbellcolor_outline = 1; ++static float vbellradius = 0.03; ++static float vbellx = 0.5; ++static float vbelly = 0.5; + + /* default TERM value */ + char *termname = "st-256color"; +diff --git a/x.c b/x.c +index 7e66c6d..eb895d4 100644 +--- a/x.c ++++ b/x.c +@@ -177,6 +177,8 @@ static int match(uint, uint); + + static void vbellbegin(); + static int isvbellcell(int x, int y); ++static void xdrawvbell(); ++static void xfillcircle(int x, int y, int r, uint color_ix); + + static void run(void); + static void usage(void); +@@ -1554,6 +1556,9 @@ xdrawline(Line line, int x1, int y1, int x2) + void + xfinishdraw(void) + { ++ if (vbellmode == 3 && win.vbellset) ++ xdrawvbell(); ++ + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, + win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, +@@ -1617,6 +1622,22 @@ xseturgency(int add) + XFree(h); + } + ++void ++xfillcircle(int x, int y, int r, uint color_ix) ++{ ++ XSetForeground(xw.dpy, dc.gc, dc.col[color_ix].pixel); ++ XFillArc(xw.dpy, xw.buf, dc.gc, x - r, y - r, r * 2, r * 2, 0, 360*64); ++} ++ ++void ++xdrawvbell() { ++ int r = round(vbellradius * (vbellradius > 0 ? win.w : -win.cw)); ++ int x = borderpx + r + vbellx * (win.tw - 2 * r); ++ int y = borderpx + r + vbelly * (win.th - 2 * r); ++ xfillcircle(x, y, r, vbellcolor_outline); ++ xfillcircle(x, y, r / 1.2, vbellcolor); /* 1.2 - an artistic choice */ ++} ++ + int + isvbellcell(int x, int y) + { +@@ -1634,7 +1655,8 @@ vbellbegin() { + if (win.vbellset) /* already visible, just extend win.lastvbell */ + return; + win.vbellset = 1; +- tfulldirt(); ++ if (vbellmode != 3) /* 3 is an overlay, no need to re-render cells */ ++ tfulldirt(); + draw(); + XFlush(xw.dpy); + } +-- +2.19.1 +