Adding sync patch ref. #21

This commit is contained in:
bakkeby 2021-05-09 09:25:22 +02:00
parent 3b88d65645
commit 56e208e0de
10 changed files with 141 additions and 2 deletions

View File

@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog: ### 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-08 - Added blinking cursor, delkey, undercurl,universcroll, desktopentry, netwmicon and osc_10_11_12_2 patches
2021-05-07 - Added xresources reload patch 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/) - [spoiler](https://st.suckless.org/patches/spoiler/)
- use inverted defaultbg/fg for selection when bg/fg are the same - 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/) - [themed-cursor](https://st.suckless.org/patches/themed_cursor/)
- instead of a default X cursor, use the xterm cursor from your cursor theme - instead of a default X cursor, use the xterm cursor from your cursor theme

View File

@ -74,6 +74,14 @@ int allowwindowops = 0;
static double minlatency = 8; static double minlatency = 8;
static double maxlatency = 33; 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 * blinking timeout (set to 0 to disable blinking) for the terminal blinking
* attribute. * attribute.

View File

@ -25,4 +25,7 @@
#endif #endif
#if SIXEL_PATCH #if SIXEL_PATCH
#include "sixel_st.c" #include "sixel_st.c"
#endif
#if SYNC_PATCH
#include "sync.c"
#endif #endif

View File

@ -25,4 +25,7 @@
#endif #endif
#if SIXEL_PATCH #if SIXEL_PATCH
#include "sixel_st.h" #include "sixel_st.h"
#endif
#if SYNC_PATCH
#include "sync.h"
#endif #endif

31
patch/sync.c Normal file
View File

@ -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;
}

7
patch/sync.h Normal file
View File

@ -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();

View File

@ -271,6 +271,19 @@
*/ */
#define SPOILER_PATCH 0 #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. /* 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 * You need to uncomment the corresponding line in config.mk to use the -lXcursor library
* when including this patch. * when including this patch.
@ -288,6 +301,10 @@
* | \- sets underline style to curvy * | \- sets underline style to curvy
* \- set underline * \- 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/ * https://st.suckless.org/patches/undercurl/
*/ */
#define UNDERCURL_PATCH 0 #define UNDERCURL_PATCH 0

33
st.c
View File

@ -904,7 +904,11 @@ ttyread(void)
int ret, written; int ret, written;
/* append read bytes to unprocessed bytes */ /* 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); ret = read(cmdfd, buf+buflen, LEN(buf)-buflen);
#endif // SYNC_PATCH
switch (ret) { switch (ret) {
case 0: case 0:
@ -912,7 +916,11 @@ ttyread(void)
case -1: case -1:
die("couldn't read from shell: %s\n", strerror(errno)); die("couldn't read from shell: %s\n", strerror(errno));
default: default:
#if SYNC_PATCH
buflen += twrite_aborted ? 0 : ret;
#else
buflen += ret; buflen += ret;
#endif // SYNC_PATCH
written = twrite(buf, buflen, 0); written = twrite(buf, buflen, 0);
buflen -= written; buflen -= written;
/* keep any incomplete UTF-8 byte sequence for the next call */ /* keep any incomplete UTF-8 byte sequence for the next call */
@ -1077,6 +1085,9 @@ tsetdirtattr(int attr)
void void
tfulldirt(void) tfulldirt(void)
{ {
#if SYNC_PATCH
tsync_end();
#endif // SYNC_PATCH
tsetdirt(0, term.row-1); tsetdirt(0, term.row-1);
} }
@ -2241,8 +2252,17 @@ strhandle(void)
tnewline(1); tnewline(1);
} }
} }
return;
#endif // SIXEL_PATCH #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 '_': /* APC -- Application Program Command */
case '^': /* PM -- Privacy Message */ case '^': /* PM -- Privacy Message */
return; return;
@ -2834,6 +2854,11 @@ twrite(const char *buf, int buflen, int show_ctrl)
Rune u; Rune u;
int n; int n;
#if SYNC_PATCH
int su0 = su;
twrite_aborted = 0;
#endif // SYNC_PATCH
for (n = 0; n < buflen; n += charsize) { for (n = 0; n < buflen; n += charsize) {
#if SIXEL_PATCH #if SIXEL_PATCH
if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) 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; u = buf[n] & 0xFF;
charsize = 1; 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 (show_ctrl && ISCONTROL(u)) {
if (u & 0x80) { if (u & 0x80) {
u &= 0x7f; u &= 0x7f;

View File

@ -1,4 +1,5 @@
st-mono| simpleterm monocolor, st-mono| simpleterm monocolor,
# undercurl patch / UNDERCURL_PATCH
Su, Su,
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
am, am,
@ -192,6 +193,8 @@ st-mono| simpleterm monocolor,
Ms=\E]52;%p1%s;%p2%s\007, Ms=\E]52;%p1%s;%p2%s\007,
Se=\E[2 q, Se=\E[2 q,
Ss=\E[%p1%d q, Ss=\E[%p1%d q,
# sync patch / SYNC_PATCH
Sync=\EP=%p1%ds\E\\,
st| simpleterm, st| simpleterm,
use=st-mono, use=st-mono,

31
x.c
View File

@ -2539,7 +2539,11 @@ run(void)
FD_SET(ttyfd, &rfd); FD_SET(ttyfd, &rfd);
FD_SET(xfd, &rfd); FD_SET(xfd, &rfd);
#if SYNC_PATCH
if (XPending(xw.dpy) || ttyread_pending())
#else
if (XPending(xw.dpy)) if (XPending(xw.dpy))
#endif // SYNC_PATCH
timeout = 0; /* existing events might not set xfd */ timeout = 0; /* existing events might not set xfd */
seltv.tv_sec = timeout / 1E3; seltv.tv_sec = timeout / 1E3;
@ -2553,8 +2557,14 @@ run(void)
} }
clock_gettime(CLOCK_MONOTONIC, &now); 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)) if (FD_ISSET(ttyfd, &rfd))
ttyread(); ttyread();
#endif // SYNC_PATCH
xev = 0; xev = 0;
while (XPending(xw.dpy)) { while (XPending(xw.dpy)) {
@ -2577,7 +2587,12 @@ run(void)
* maximum latency intervals during `cat huge.txt`, and perfect * maximum latency intervals during `cat huge.txt`, and perfect
* sync with periodic updates from animations/key-repeats/etc. * 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) { if (!drawing) {
trigger = now; trigger = now;
#if BLINKING_CURSOR_PATCH #if BLINKING_CURSOR_PATCH
@ -2594,6 +2609,20 @@ run(void)
continue; /* we have time, try to find idle */ 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 */ /* idle detected or maxlatency exhausted -> draw */
timeout = -1; timeout = -1;
#if BLINKING_CURSOR_PATCH #if BLINKING_CURSOR_PATCH