st-visualbell2-basic-2018-10-16-30ec9a3.diff (5437B)
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] [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