commit 56e208e0dee6ca3390d388a462d04dba0c38c564
parent 3b88d65645ebc89f662d1b17e43a2e582d69c199
Author: bakkeby <bakkeby@gmail.com>
Date: Sun, 9 May 2021 09:25:22 +0200
Adding sync patch ref. #21
Diffstat:
10 files changed, 143 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
@@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog:
+2021-05-09 - Added the sync patch
+
2021-05-08 - Added blinking cursor, delkey, undercurl,universcroll, desktopentry, netwmicon and osc_10_11_12_2 patches
2021-05-07 - Added xresources reload patch
@@ -184,6 +186,11 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
- [spoiler](https://st.suckless.org/patches/spoiler/)
- use inverted defaultbg/fg for selection when bg/fg are the same
+ - [sync](https://st.suckless.org/patches/sync/)
+ - adds synchronized-updates/application-sync support in st
+ - this has no effect except when an application uses the synchronized-update escape sequences
+ - with this patch nearly all cursor flicker is eliminated in tmux, and tmux detects it automatically via terminfo
+
- [themed-cursor](https://st.suckless.org/patches/themed_cursor/)
- instead of a default X cursor, use the xterm cursor from your cursor theme
diff --git a/config.def.h b/config.def.h
@@ -74,6 +74,14 @@ int allowwindowops = 0;
static double minlatency = 8;
static double maxlatency = 33;
+#if SYNC_PATCH
+/*
+ * Synchronized-Update timeout in ms
+ * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
+ */
+static uint su_timeout = 200;
+#endif // SYNC_PATCH
+
/*
* blinking timeout (set to 0 to disable blinking) for the terminal blinking
* attribute.
diff --git a/patch/st_include.c b/patch/st_include.c
@@ -25,4 +25,7 @@
#endif
#if SIXEL_PATCH
#include "sixel_st.c"
+#endif
+#if SYNC_PATCH
+#include "sync.c"
#endif
\ No newline at end of file
diff --git a/patch/st_include.h b/patch/st_include.h
@@ -25,4 +25,7 @@
#endif
#if SIXEL_PATCH
#include "sixel_st.h"
+#endif
+#if SYNC_PATCH
+#include "sync.h"
#endif
\ No newline at end of file
diff --git a/patch/sync.c b/patch/sync.c
@@ -0,0 +1,31 @@
+#include <time.h>
+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;
+}
+
+int
+ttyread_pending()
+{
+ return twrite_aborted;
+}
+\ No newline at end of file
diff --git a/patch/sync.h b/patch/sync.h
@@ -0,0 +1,7 @@
+static int su = 0;
+static int twrite_aborted = 0;
+
+static void tsync_begin();
+static void tsync_end();
+int tinsync(uint timeout);
+int ttyread_pending();
+\ No newline at end of file
diff --git a/patches.def.h b/patches.def.h
@@ -271,6 +271,19 @@
*/
#define SPOILER_PATCH 0
+/* This patch adds synchronized-updates/application-sync support in st.
+ * This will have no effect except when an application uses the synchronized-update escape
+ * sequences. With this patch nearly all cursor flicker is eliminated in tmux, and tmux detects
+ * it automatically via terminfo.
+ *
+ * Note: this patch alters st.info to promote support for extra escape sequences, which can
+ * potentially cause application misbehaviour if you do not use this patch. Try removing or
+ * commenting out the corresponding line in st.info if this is causing issues.
+ *
+ * https://st.suckless.org/patches/sync/
+ */
+#define SYNC_PATCH 0
+
/* Instead of a default X cursor, use the xterm cursor from your cursor theme.
* You need to uncomment the corresponding line in config.mk to use the -lXcursor library
* when including this patch.
@@ -288,6 +301,10 @@
* | \- sets underline style to curvy
* \- set underline
*
+ * Note: this patch alters st.info to promote support for extra escape sequences, which can
+ * potentially cause application misbehaviour if you do not use this patch. Try removing or
+ * commenting out the corresponding line in st.info if this is causing issues.
+ *
* https://st.suckless.org/patches/undercurl/
*/
#define UNDERCURL_PATCH 0
diff --git a/st.c b/st.c
@@ -904,7 +904,11 @@ ttyread(void)
int ret, written;
/* append read bytes to unprocessed bytes */
+ #if SYNC_PATCH
+ ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen);
+ #else
ret = read(cmdfd, buf+buflen, LEN(buf)-buflen);
+ #endif // SYNC_PATCH
switch (ret) {
case 0:
@@ -912,7 +916,11 @@ ttyread(void)
case -1:
die("couldn't read from shell: %s\n", strerror(errno));
default:
+ #if SYNC_PATCH
+ buflen += twrite_aborted ? 0 : ret;
+ #else
buflen += ret;
+ #endif // SYNC_PATCH
written = twrite(buf, buflen, 0);
buflen -= written;
/* keep any incomplete UTF-8 byte sequence for the next call */
@@ -1077,6 +1085,9 @@ tsetdirtattr(int attr)
void
tfulldirt(void)
{
+ #if SYNC_PATCH
+ tsync_end();
+ #endif // SYNC_PATCH
tsetdirt(0, term.row-1);
}
@@ -2241,8 +2252,17 @@ strhandle(void)
tnewline(1);
}
}
- return;
#endif // SIXEL_PATCH
+ #if SYNC_PATCH
+ /* 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 */
+ #endif // SYNC_PATCH
+ #if SIXEL_PATCH || SYNC_PATCH
+ return;
+ #endif // SIXEL_PATCH | SYNC_PATCH
case '_': /* APC -- Application Program Command */
case '^': /* PM -- Privacy Message */
return;
@@ -2834,6 +2854,11 @@ twrite(const char *buf, int buflen, int show_ctrl)
Rune u;
int n;
+ #if SYNC_PATCH
+ int su0 = su;
+ twrite_aborted = 0;
+ #endif // SYNC_PATCH
+
for (n = 0; n < buflen; n += charsize) {
#if SIXEL_PATCH
if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL))
@@ -2849,6 +2874,12 @@ twrite(const char *buf, int buflen, int show_ctrl)
u = buf[n] & 0xFF;
charsize = 1;
}
+ #if SYNC_PATCH
+ if (su0 && !su) {
+ twrite_aborted = 1;
+ break; // ESU - allow rendering before a new BSU
+ }
+ #endif // SYNC_PATCH
if (show_ctrl && ISCONTROL(u)) {
if (u & 0x80) {
u &= 0x7f;
diff --git a/st.info b/st.info
@@ -1,4 +1,5 @@
st-mono| simpleterm monocolor,
+# undercurl patch / UNDERCURL_PATCH
Su,
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
am,
@@ -192,6 +193,8 @@ st-mono| simpleterm monocolor,
Ms=\E]52;%p1%s;%p2%s\007,
Se=\E[2 q,
Ss=\E[%p1%d q,
+# sync patch / SYNC_PATCH
+ Sync=\EP=%p1%ds\E\\,
st| simpleterm,
use=st-mono,
diff --git a/x.c b/x.c
@@ -2539,7 +2539,11 @@ run(void)
FD_SET(ttyfd, &rfd);
FD_SET(xfd, &rfd);
+ #if SYNC_PATCH
+ if (XPending(xw.dpy) || ttyread_pending())
+ #else
if (XPending(xw.dpy))
+ #endif // SYNC_PATCH
timeout = 0; /* existing events might not set xfd */
seltv.tv_sec = timeout / 1E3;
@@ -2553,8 +2557,14 @@ run(void)
}
clock_gettime(CLOCK_MONOTONIC, &now);
+ #if SYNC_PATCH
+ int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
+ if (ttyin)
+ ttyread();
+ #else
if (FD_ISSET(ttyfd, &rfd))
ttyread();
+ #endif // SYNC_PATCH
xev = 0;
while (XPending(xw.dpy)) {
@@ -2577,7 +2587,12 @@ 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 SYNC_PATCH
+ if (ttyin || xev)
+ #else
+ if (FD_ISSET(ttyfd, &rfd) || xev)
+ #endif // SYNC_PATCH
+ {
if (!drawing) {
trigger = now;
#if BLINKING_CURSOR_PATCH
@@ -2594,6 +2609,20 @@ run(void)
continue; /* we have time, try to find idle */
}
+ #if SYNC_PATCH
+ 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;
+ }
+ #endif // SYNC_PATCH
+
/* idle detected or maxlatency exhausted -> draw */
timeout = -1;
#if BLINKING_CURSOR_PATCH