| st-visualbell2-enhanced-2018-10-16-30ec9a3.diff - sites - public wiki contents … | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| 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)" <[email protected]> | |
| 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 … | |
| 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) > blinktim… | |
| 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-c… | |
| 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.lastv… | |
| 167 + if (remain <= 0) { | |
| 168 + dodraw = 1; | |
| 169 + remain = -1; /* draw (clear), and that'… | |
| 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, &r… | |
| 182 - if (blinkset) { | |
| 183 - if (TIMEDIFF(now, lastblink) \ | |
| 184 - > blinktimeout)… | |
| 185 - drawtimeout.tv_nsec = 1… | |
| 186 - } else { | |
| 187 - drawtimeout.tv_nsec = (… | |
| 188 - (blinktimeout -… | |
| 189 - TIMEDIFF(now, | |
| 190 - lastbli… | |
| 191 - } | |
| 192 - drawtimeout.tv_sec = \ | |
| 193 - drawtimeout.tv_nsec / 1E9; | |
| 194 - drawtimeout.tv_nsec %= (long)1E… | |
| 195 + if (to_ms >= 0) { | |
| 196 + static const long k = 1E3, m = … | |
| 197 + drawtimeout.tv_sec = to_ms / k; | |
| 198 + drawtimeout.tv_nsec = (to_ms % … | |
| 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)" <[email protected]> | |
| 208 Date: Tue, 16 Oct 2018 16:04:45 +0300 | |
| 209 Subject: [PATCH 2/2] [vbell2] visual bell: experimental circle rendering… | |
| 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… | |
| 240 + * - position: relative to window width/height (0 and 1 are at the edge… | |
| 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, … | |
| 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 ch… | |
| 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 ce… | |
| 302 + tfulldirt(); | |
| 303 draw(); | |
| 304 XFlush(xw.dpy); | |
| 305 } | |
| 306 -- | |
| 307 2.19.1 | |
| 308 |