Introduction
Introduction Statistics Contact Development Disclaimer Help
st-appsync-0.8.3.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-appsync-0.8.3.diff (7593B)
---
1 From 97bdda00d211f989ee42c02a08e96b41800544f4 Mon Sep 17 00:00:00 2001
2 From: "Avi Halachmi (:avih)" <[email protected]>
3 Date: Sat, 18 Apr 2020 13:56:11 +0300
4 Subject: [PATCH] application-sync: support Synchronized-Updates
5
6 See https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
7
8 In a nutshell: allow an application to suspend drawing until it has
9 completed some output - so that the terminal will not flicker/tear by
10 rendering partial content. If the end-of-suspension sequence doesn't
11 arrive, the terminal bails out after a timeout (default: 200 ms).
12
13 The feature is supported and pioneered by iTerm2. There are probably
14 very few other terminals or applications which support this feature
15 currently.
16
17 One notable application which does support it is tmux (master as of
18 2020-04-18) - where cursor flicker is completely avoided when a pane
19 has new content. E.g. run in one pane: `while :; do cat x.c; done'
20 while the cursor is at another pane.
21
22 The terminfo string `Sync' added to `st.info' is also a tmux extension
23 which tmux detects automatically when `st.info` is installed.
24
25 Notes:
26
27 - Draw-suspension begins on BSU sequence (Begin-Synchronized-Update),
28 and ends on ESU sequence (End-Synchronized-Update).
29
30 - BSU, ESU are "\033P=1s\033\\", "\033P=2s\033\\" respectively (DCS).
31
32 - SU doesn't support nesting - BSU begins or extends, ESU always ends.
33
34 - ESU without BSU is ignored.
35
36 - BSU after BSU extends (resets the timeout), so an application could
37 send BSU in a loop and keep drawing suspended - exactly like it can
38 not-draw anything in a loop. But as soon as it exits/aborted then
39 drawing is resumed according to the timeout even without ESU.
40
41 - This implementation focuses on ESU and doesn't really care about BSU
42 in the sense that it tries hard to draw exactly once ESU arrives (if
43 it's not too soon after the last draw - according to minlatency),
44 and doesn't try to draw the content just up-to BSU. These two sides
45 complement eachother - not-drawing on BSU increases the chance that
46 ESU is not too soon after the last draw. This approach was chosen
47 because the application's main focus is that ESU indicates to the
48 terminal that the content is now ready - and that's when we try to
49 draw.
50 ---
51 config.def.h | 6 ++++++
52 st.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
53 st.info | 1 +
54 x.c | 22 +++++++++++++++++++---
55 4 files changed, 72 insertions(+), 5 deletions(-)
56
57 diff --git a/config.def.h b/config.def.h
58 index fdbacfd..d44c28e 100644
59 --- a/config.def.h
60 +++ b/config.def.h
61 @@ -52,6 +52,12 @@ int allowaltscreen = 1;
62 static double minlatency = 8;
63 static double maxlatency = 33;
64
65 +/*
66 + * Synchronized-Update timeout in ms
67 + * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
68 + */
69 +static uint su_timeout = 200;
70 +
71 /*
72 * blinking timeout (set to 0 to disable blinking) for the terminal bli…
73 * attribute.
74 diff --git a/st.c b/st.c
75 index 0ce6ac2..d53b882 100644
76 --- a/st.c
77 +++ b/st.c
78 @@ -232,6 +232,33 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0x…
79 static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10…
80 static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10F…
81
82 +#include <time.h>
83 +static int su = 0;
84 +struct timespec sutv;
85 +
86 +static void
87 +tsync_begin()
88 +{
89 + clock_gettime(CLOCK_MONOTONIC, &sutv);
90 + su = 1;
91 +}
92 +
93 +static void
94 +tsync_end()
95 +{
96 + su = 0;
97 +}
98 +
99 +int
100 +tinsync(uint timeout)
101 +{
102 + struct timespec now;
103 + if (su && !clock_gettime(CLOCK_MONOTONIC, &now)
104 + && TIMEDIFF(now, sutv) >= timeout)
105 + su = 0;
106 + return su;
107 +}
108 +
109 ssize_t
110 xwrite(int fd, const char *s, size_t len)
111 {
112 @@ -818,6 +845,9 @@ ttynew(char *line, char *cmd, char *out, char **args)
113 return cmdfd;
114 }
115
116 +static int twrite_aborted = 0;
117 +int ttyread_pending() { return twrite_aborted; }
118 +
119 size_t
120 ttyread(void)
121 {
122 @@ -826,7 +856,7 @@ ttyread(void)
123 int ret, written;
124
125 /* append read bytes to unprocessed bytes */
126 - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen);
127 + ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buf…
128
129 switch (ret) {
130 case 0:
131 @@ -834,7 +864,7 @@ ttyread(void)
132 case -1:
133 die("couldn't read from shell: %s\n", strerror(errno));
134 default:
135 - buflen += ret;
136 + buflen += twrite_aborted ? 0 : ret;
137 written = twrite(buf, buflen, 0);
138 buflen -= written;
139 /* keep any incomplete UTF-8 byte sequence for the next…
140 @@ -995,6 +1025,7 @@ tsetdirtattr(int attr)
141 void
142 tfulldirt(void)
143 {
144 + tsync_end();
145 tsetdirt(0, term.row-1);
146 }
147
148 @@ -1901,6 +1932,12 @@ strhandle(void)
149 return;
150 case 'P': /* DCS -- Device Control String */
151 term.mode |= ESC_DCS;
152 + /* https://gitlab.com/gnachman/iterm2/-/wikis/synchroni…
153 + if (strstr(strescseq.buf, "=1s") == strescseq.buf)
154 + tsync_begin(), term.mode &= ~ESC_DCS; /* BSU */
155 + else if (strstr(strescseq.buf, "=2s") == strescseq.buf)
156 + tsync_end(), term.mode &= ~ESC_DCS; /* ESU */
157 + return;
158 case '_': /* APC -- Application Program Command */
159 case '^': /* PM -- Privacy Message */
160 return;
161 @@ -2454,6 +2491,9 @@ twrite(const char *buf, int buflen, int show_ctrl)
162 Rune u;
163 int n;
164
165 + int su0 = su;
166 + twrite_aborted = 0;
167 +
168 for (n = 0; n < buflen; n += charsize) {
169 if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
170 /* process a complete utf8 char */
171 @@ -2464,6 +2504,10 @@ twrite(const char *buf, int buflen, int show_ctrl)
172 u = buf[n] & 0xFF;
173 charsize = 1;
174 }
175 + if (su0 && !su) {
176 + twrite_aborted = 1;
177 + break; // ESU - allow rendering before a new B…
178 + }
179 if (show_ctrl && ISCONTROL(u)) {
180 if (u & 0x80) {
181 u &= 0x7f;
182 diff --git a/st.info b/st.info
183 index e2abc98..0a781db 100644
184 --- a/st.info
185 +++ b/st.info
186 @@ -188,6 +188,7 @@ st-mono| simpleterm monocolor,
187 Ms=\E]52;%p1%s;%p2%s\007,
188 Se=\E[2 q,
189 Ss=\E[%p1%d q,
190 + Sync=\EP=%p1%ds\E\\,
191
192 st| simpleterm,
193 use=st-mono,
194 diff --git a/x.c b/x.c
195 index cbbd11f..38b08a8 100644
196 --- a/x.c
197 +++ b/x.c
198 @@ -1861,6 +1861,9 @@ resize(XEvent *e)
199 cresize(e->xconfigure.width, e->xconfigure.height);
200 }
201
202 +int tinsync(uint);
203 +int ttyread_pending();
204 +
205 void
206 run(void)
207 {
208 @@ -1895,7 +1898,7 @@ run(void)
209 FD_SET(ttyfd, &rfd);
210 FD_SET(xfd, &rfd);
211
212 - if (XPending(xw.dpy))
213 + if (XPending(xw.dpy) || ttyread_pending())
214 timeout = 0; /* existing events might not set …
215
216 seltv.tv_sec = timeout / 1E3;
217 @@ -1909,7 +1912,8 @@ run(void)
218 }
219 clock_gettime(CLOCK_MONOTONIC, &now);
220
221 - if (FD_ISSET(ttyfd, &rfd))
222 + int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
223 + if (ttyin)
224 ttyread();
225
226 xev = 0;
227 @@ -1933,7 +1937,7 @@ run(void)
228 * maximum latency intervals during `cat huge.txt`, and…
229 * sync with periodic updates from animations/key-repea…
230 */
231 - if (FD_ISSET(ttyfd, &rfd) || xev) {
232 + if (ttyin || xev) {
233 if (!drawing) {
234 trigger = now;
235 drawing = 1;
236 @@ -1944,6 +1948,18 @@ run(void)
237 continue; /* we have time, try to find…
238 }
239
240 + if (tinsync(su_timeout)) {
241 + /*
242 + * on synchronized-update draw-suspension: don'…
243 + * drawing so that we draw ASAP once we can (ju…
244 + * ESU). it won't be too soon because we alread…
245 + * draw now but we skip. we set timeout > 0 to …
246 + * SU-timeout even without new content.
247 + */
248 + timeout = minlatency;
249 + continue;
250 + }
251 +
252 /* idle detected or maxlatency exhausted -> draw */
253 timeout = -1;
254 if (blinktimeout && tattrset(ATTR_BLINK)) {
255
256 base-commit: 43a395ae91f7d67ce694e65edeaa7bbc720dd027
257 prerequisite-patch-id: d7d5e516bc74afe094ffbfc3edb19c11d49df4e7
258 --
259 2.17.1
260
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.