diff options
Diffstat (limited to 'patches')
-rw-r--r-- | patches/st-appsync-20200618-b27a383.diff | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/patches/st-appsync-20200618-b27a383.diff b/patches/st-appsync-20200618-b27a383.diff deleted file mode 100644 index 4736325..0000000 --- a/patches/st-appsync-20200618-b27a383.diff +++ /dev/null @@ -1,259 +0,0 @@ -From 8c9c920325fa10440a96736ba58ec647a0365e22 Mon Sep 17 00:00:00 2001 -From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> -Date: Sat, 18 Apr 2020 13:56:11 +0300 -Subject: [PATCH] application-sync: support Synchronized-Updates - -See https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec - -In a nutshell: allow an application to suspend drawing until it has -completed some output - so that the terminal will not flicker/tear by -rendering partial content. If the end-of-suspension sequence doesn't -arrive, the terminal bails out after a timeout (default: 200 ms). - -The feature is supported and pioneered by iTerm2. There are probably -very few other terminals or applications which support this feature -currently. - -One notable application which does support it is tmux (master as of -2020-04-18) - where cursor flicker is completely avoided when a pane -has new content. E.g. run in one pane: `while :; do cat x.c; done' -while the cursor is at another pane. - -The terminfo string `Sync' added to `st.info' is also a tmux extension -which tmux detects automatically when `st.info` is installed. - -Notes: - -- Draw-suspension begins on BSU sequence (Begin-Synchronized-Update), - and ends on ESU sequence (End-Synchronized-Update). - -- BSU, ESU are "\033P=1s\033\\", "\033P=2s\033\\" respectively (DCS). - -- SU doesn't support nesting - BSU begins or extends, ESU always ends. - -- ESU without BSU is ignored. - -- BSU after BSU extends (resets the timeout), so an application could - send BSU in a loop and keep drawing suspended - exactly like it can - not-draw anything in a loop. But as soon as it exits/aborted then - drawing is resumed according to the timeout even without ESU. - -- This implementation focuses on ESU and doesn't really care about BSU - in the sense that it tries hard to draw exactly once ESU arrives (if - it's not too soon after the last draw - according to minlatency), - and doesn't try to draw the content just up-to BSU. These two sides - complement eachother - not-drawing on BSU increases the chance that - ESU is not too soon after the last draw. This approach was chosen - because the application's main focus is that ESU indicates to the - terminal that the content is now ready - and that's when we try to - draw. ---- - config.def.h | 6 ++++++ - st.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- - st.info | 1 + - x.c | 22 +++++++++++++++++++--- - 4 files changed, 72 insertions(+), 5 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 6f05dce..80d768e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -56,6 +56,12 @@ int allowwindowops = 0; - static double minlatency = 8; - static double maxlatency = 33; - -+/* -+ * Synchronized-Update timeout in ms -+ * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec -+ */ -+static uint su_timeout = 200; -+ - /* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. -diff --git a/st.c b/st.c -index 76b7e0d..0582e77 100644 ---- a/st.c -+++ b/st.c -@@ -231,6 +231,33 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; - static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; - static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -+#include <time.h> -+static int su = 0; -+struct timespec sutv; -+ -+static void -+tsync_begin() -+{ -+ clock_gettime(CLOCK_MONOTONIC, &sutv); -+ su = 1; -+} -+ -+static void -+tsync_end() -+{ -+ su = 0; -+} -+ -+int -+tinsync(uint timeout) -+{ -+ struct timespec now; -+ if (su && !clock_gettime(CLOCK_MONOTONIC, &now) -+ && TIMEDIFF(now, sutv) >= timeout) -+ su = 0; -+ return su; -+} -+ - ssize_t - xwrite(int fd, const char *s, size_t len) - { -@@ -818,6 +845,9 @@ ttynew(char *line, char *cmd, char *out, char **args) - return cmdfd; - } - -+static int twrite_aborted = 0; -+int ttyread_pending() { return twrite_aborted; } -+ - size_t - ttyread(void) - { -@@ -826,7 +856,7 @@ ttyread(void) - int ret, written; - - /* append read bytes to unprocessed bytes */ -- ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); -+ ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: -@@ -834,7 +864,7 @@ ttyread(void) - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: -- buflen += ret; -+ buflen += twrite_aborted ? 0 : ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ -@@ -994,6 +1024,7 @@ tsetdirtattr(int attr) - void - tfulldirt(void) - { -+ tsync_end(); - tsetdirt(0, term.row-1); - } - -@@ -1895,6 +1926,12 @@ strhandle(void) - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ -+ /* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */ -+ if (strstr(strescseq.buf, "=1s") == strescseq.buf) -+ tsync_begin(); /* BSU */ -+ else if (strstr(strescseq.buf, "=2s") == strescseq.buf) -+ tsync_end(); /* ESU */ -+ return; - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; -@@ -2436,6 +2473,9 @@ twrite(const char *buf, int buflen, int show_ctrl) - Rune u; - int n; - -+ int su0 = su; -+ twrite_aborted = 0; -+ - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ -@@ -2446,6 +2486,10 @@ twrite(const char *buf, int buflen, int show_ctrl) - u = buf[n] & 0xFF; - charsize = 1; - } -+ if (su0 && !su) { -+ twrite_aborted = 1; -+ break; // ESU - allow rendering before a new BSU -+ } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; -diff --git a/st.info b/st.info -index 8201ad6..b32b446 100644 ---- a/st.info -+++ b/st.info -@@ -191,6 +191,7 @@ st-mono| simpleterm monocolor, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, -+ Sync=\EP=%p1%ds\E\\, - - st| simpleterm, - use=st-mono, -diff --git a/x.c b/x.c -index 210f184..27ff4e2 100644 ---- a/x.c -+++ b/x.c -@@ -1861,6 +1861,9 @@ resize(XEvent *e) - cresize(e->xconfigure.width, e->xconfigure.height); - } - -+int tinsync(uint); -+int ttyread_pending(); -+ - void - run(void) - { -@@ -1895,7 +1898,7 @@ run(void) - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - -- if (XPending(xw.dpy)) -+ if (XPending(xw.dpy) || ttyread_pending()) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; -@@ -1909,7 +1912,8 @@ run(void) - } - clock_gettime(CLOCK_MONOTONIC, &now); - -- if (FD_ISSET(ttyfd, &rfd)) -+ int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending(); -+ if (ttyin) - ttyread(); - - xev = 0; -@@ -1933,7 +1937,7 @@ run(void) - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ -- if (FD_ISSET(ttyfd, &rfd) || xev) { -+ if (ttyin || xev) { - if (!drawing) { - trigger = now; - drawing = 1; -@@ -1944,6 +1948,18 @@ run(void) - continue; /* we have time, try to find idle */ - } - -+ if (tinsync(su_timeout)) { -+ /* -+ * on synchronized-update draw-suspension: don't reset -+ * drawing so that we draw ASAP once we can (just after -+ * ESU). it won't be too soon because we already can -+ * draw now but we skip. we set timeout > 0 to draw on -+ * SU-timeout even without new content. -+ */ -+ timeout = minlatency; -+ continue; -+ } -+ - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - -base-commit: b27a383a3acc7decf00e6e889fca265430b5d329 --- -2.17.1 - |