Compare commits
18 commits
a5559a1e22
...
a2a704492b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a2a704492b | ||
![]() |
0f8b40652b | ||
![]() |
e6e2c6199f | ||
![]() |
94b8ec0021 | ||
![]() |
dec6b530a4 | ||
![]() |
475a0a36cb | ||
![]() |
e8392b282c | ||
![]() |
f8afebdfa0 | ||
![]() |
bda9c9ffa6 | ||
![]() |
045a0fab4f | ||
![]() |
9c30066e73 | ||
![]() |
8304d4f059 | ||
![]() |
914fb825df | ||
![]() |
cde480c693 | ||
![]() |
8211e36d28 | ||
![]() |
87545c612e | ||
![]() |
1d59091065 | ||
![]() |
d6ea0a1a61 |
6 changed files with 163 additions and 106 deletions
59
FAQ
59
FAQ
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task.
|
Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task.
|
||||||
|
|
||||||
|
|
||||||
## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever!
|
## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever!
|
||||||
|
|
||||||
It means that st doesn’t have any terminfo entry on your system. Chances are
|
It means that st doesn’t have any terminfo entry on your system. Chances are
|
||||||
you did not `make install`. If you just want to test it without installing it,
|
you did not `make install`. If you just want to test it without installing it,
|
||||||
you can manually run `tic -sx st.info`.
|
you can manually run `tic -sx st.info`.
|
||||||
|
|
||||||
|
|
||||||
## Nothing works, and nothing is said about an unknown terminal!
|
## Nothing works, and nothing is said about an unknown terminal!
|
||||||
|
|
||||||
* Some programs just assume they’re running in xterm i.e. they don’t rely on
|
* Some programs just assume they’re running in xterm i.e. they don’t rely on
|
||||||
|
@ -15,6 +17,7 @@ you can manually run `tic -sx st.info`.
|
||||||
* Some programs don’t complain about the lacking st description and default to
|
* Some programs don’t complain about the lacking st description and default to
|
||||||
another terminal. In that case see the question about terminfo.
|
another terminal. In that case see the question about terminfo.
|
||||||
|
|
||||||
|
|
||||||
## How do I scroll back up?
|
## How do I scroll back up?
|
||||||
|
|
||||||
* Using a terminal multiplexer.
|
* Using a terminal multiplexer.
|
||||||
|
@ -23,11 +26,13 @@ you can manually run `tic -sx st.info`.
|
||||||
* Using the excellent tool of [scroll](https://git.suckless.org/scroll/).
|
* Using the excellent tool of [scroll](https://git.suckless.org/scroll/).
|
||||||
* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/).
|
* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/).
|
||||||
|
|
||||||
|
|
||||||
## I would like to have utmp and/or scroll functionality by default
|
## I would like to have utmp and/or scroll functionality by default
|
||||||
|
|
||||||
You can add the absolute patch of both programs in your config.h
|
You can add the absolute patch of both programs in your config.h
|
||||||
file. You only have to modify the value of utmp and scroll variables.
|
file. You only have to modify the value of utmp and scroll variables.
|
||||||
|
|
||||||
|
|
||||||
## Why doesn't the Del key work in some programs?
|
## Why doesn't the Del key work in some programs?
|
||||||
|
|
||||||
Taken from the terminfo manpage:
|
Taken from the terminfo manpage:
|
||||||
|
@ -83,12 +88,14 @@ If you are using zsh, then read the zsh FAQ
|
||||||
|
|
||||||
Putting these lines into your .zshrc will fix the problems.
|
Putting these lines into your .zshrc will fix the problems.
|
||||||
|
|
||||||
|
|
||||||
## How can I use meta in 8bit mode?
|
## How can I use meta in 8bit mode?
|
||||||
|
|
||||||
St supports meta in 8bit mode, but the default terminfo entry doesn't
|
St supports meta in 8bit mode, but the default terminfo entry doesn't
|
||||||
use this capability. If you want it, you have to use the 'st-meta' value
|
use this capability. If you want it, you have to use the 'st-meta' value
|
||||||
in TERM.
|
in TERM.
|
||||||
|
|
||||||
|
|
||||||
## I cannot compile st in OpenBSD
|
## I cannot compile st in OpenBSD
|
||||||
|
|
||||||
OpenBSD lacks librt, despite it being mandatory in POSIX
|
OpenBSD lacks librt, despite it being mandatory in POSIX
|
||||||
|
@ -97,6 +104,7 @@ If you want to compile st for OpenBSD you have to remove -lrt from config.mk, an
|
||||||
st will compile without any loss of functionality, because all the functions are
|
st will compile without any loss of functionality, because all the functions are
|
||||||
included in libc on this platform.
|
included in libc on this platform.
|
||||||
|
|
||||||
|
|
||||||
## The Backspace Case
|
## The Backspace Case
|
||||||
|
|
||||||
St is emulating the Linux way of handling backspace being delete and delete being
|
St is emulating the Linux way of handling backspace being delete and delete being
|
||||||
|
@ -158,19 +166,60 @@ terminal users wants its backspace to be how he feels it:
|
||||||
[1] http://www.ibb.net/~anne/keyboard.html
|
[1] http://www.ibb.net/~anne/keyboard.html
|
||||||
[2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html
|
[2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html
|
||||||
|
|
||||||
|
|
||||||
## But I really want the old grumpy behaviour of my terminal
|
## But I really want the old grumpy behaviour of my terminal
|
||||||
|
|
||||||
Apply [1].
|
Apply [1].
|
||||||
|
|
||||||
[1] https://st.suckless.org/patches/delkey
|
[1] https://st.suckless.org/patches/delkey
|
||||||
|
|
||||||
## Why do images not work in st (in programs such as w3m)?
|
|
||||||
|
|
||||||
This is a terrible hack that overdraws an image on top of the terminal emulator
|
## Why do images not work in st using the w3m image hack?
|
||||||
window. It also relies on a very specific way the terminal draws it's contents.
|
|
||||||
|
w3mimg uses a hack that draws an image on top of the terminal emulator Drawable
|
||||||
|
window. The hack relies on the terminal to use a single buffer to draw its
|
||||||
|
contents directly.
|
||||||
|
|
||||||
|
st uses double-buffered drawing so the image is quickly replaced and may show a
|
||||||
|
short flicker effect.
|
||||||
|
|
||||||
|
Below is a patch example to change st double-buffering to a single Drawable
|
||||||
|
buffer.
|
||||||
|
|
||||||
|
diff --git a/x.c b/x.c
|
||||||
|
--- a/x.c
|
||||||
|
+++ b/x.c
|
||||||
|
@@ -561,10 +561,6 @@ xresize(int col, int row)
|
||||||
|
win.tw = MAX(1, col * win.cw);
|
||||||
|
win.th = MAX(1, row * win.ch);
|
||||||
|
|
||||||
|
- XFreePixmap(xw.dpy, xw.buf);
|
||||||
|
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
||||||
|
- DefaultDepth(xw.dpy, xw.scr));
|
||||||
|
- XftDrawChange(xw.draw, xw.buf);
|
||||||
|
xclear(0, 0, win.w, win.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -921,8 +917,7 @@ xinit(void)
|
||||||
|
gcvalues.graphics_exposures = False;
|
||||||
|
dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
|
||||||
|
&gcvalues);
|
||||||
|
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
||||||
|
- DefaultDepth(xw.dpy, xw.scr));
|
||||||
|
+ xw.buf = xw.win;
|
||||||
|
XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
|
||||||
|
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
|
||||||
|
|
||||||
|
@@ -1386,8 +1381,6 @@ void
|
||||||
|
draw(void)
|
||||||
|
{
|
||||||
|
drawregion(0, 0, term.col, term.row);
|
||||||
|
- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
|
||||||
|
- win.h, 0, 0);
|
||||||
|
XSetForeground(xw.dpy, dc.gc,
|
||||||
|
dc.col[IS_SET(MODE_REVERSE)?
|
||||||
|
defaultfg : defaultbg].pixel);
|
||||||
|
|
||||||
A more proper (but limited way) would be using sixels. Which st doesn't
|
|
||||||
support.
|
|
||||||
|
|
||||||
## BadLength X error in Xft when trying to render emoji
|
## BadLength X error in Xft when trying to render emoji
|
||||||
|
|
||||||
|
|
17
config.def.h
17
config.def.h
|
@ -43,9 +43,18 @@ static unsigned int tripleclicktimeout = 600;
|
||||||
/* alt screens */
|
/* alt screens */
|
||||||
int allowaltscreen = 1;
|
int allowaltscreen = 1;
|
||||||
|
|
||||||
/* frames per second st should at maximum draw to the screen */
|
/* allow certain non-interactive (insecure) window operations such as:
|
||||||
static unsigned int xfps = 120;
|
setting the clipboard text */
|
||||||
static unsigned int actionfps = 30;
|
int allowwindowops = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* draw latency range in ms - from new content/keypress/etc until drawing.
|
||||||
|
* within this range, st draws when content stops arriving (idle). mostly it's
|
||||||
|
* near minlatency, but it waits longer for slow updates to avoid partial draw.
|
||||||
|
* low minlatency will tear/flicker more, as it can "detect" idle too early.
|
||||||
|
*/
|
||||||
|
static double minlatency = 8;
|
||||||
|
static double maxlatency = 33;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* blinking timeout (set to 0 to disable blinking) for the terminal blinking
|
* blinking timeout (set to 0 to disable blinking) for the terminal blinking
|
||||||
|
@ -166,7 +175,9 @@ static uint forcemousemod = ShiftMask;
|
||||||
static MouseShortcut mshortcuts[] = {
|
static MouseShortcut mshortcuts[] = {
|
||||||
/* mask button function argument release */
|
/* mask button function argument release */
|
||||||
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
||||||
|
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
|
||||||
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
||||||
|
{ ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
|
||||||
{ XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
|
{ XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
59
st.c
59
st.c
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
||||||
#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177')
|
#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f)
|
||||||
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
||||||
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
||||||
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
||||||
|
@ -129,6 +129,7 @@ typedef struct {
|
||||||
int charset; /* current charset */
|
int charset; /* current charset */
|
||||||
int icharset; /* selected charset for sequence */
|
int icharset; /* selected charset for sequence */
|
||||||
int *tabs;
|
int *tabs;
|
||||||
|
Rune lastc; /* last printed char outside of sequence, 0 if control */
|
||||||
} Term;
|
} Term;
|
||||||
|
|
||||||
/* CSI Escape sequence structs */
|
/* CSI Escape sequence structs */
|
||||||
|
@ -634,7 +635,8 @@ getsel(void)
|
||||||
* st.
|
* st.
|
||||||
* FIXME: Fix the computer world.
|
* FIXME: Fix the computer world.
|
||||||
*/
|
*/
|
||||||
if ((y < sel.ne.y || lastx >= linelen) && !(last->mode & ATTR_WRAP))
|
if ((y < sel.ne.y || lastx >= linelen) &&
|
||||||
|
(!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR))
|
||||||
*ptr++ = '\n';
|
*ptr++ = '\n';
|
||||||
}
|
}
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
|
@ -730,7 +732,7 @@ sigchld(int a)
|
||||||
die("child exited with status %d\n", WEXITSTATUS(stat));
|
die("child exited with status %d\n", WEXITSTATUS(stat));
|
||||||
else if (WIFSIGNALED(stat))
|
else if (WIFSIGNALED(stat))
|
||||||
die("child terminated due to signal %d\n", WTERMSIG(stat));
|
die("child terminated due to signal %d\n", WTERMSIG(stat));
|
||||||
exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -841,7 +843,6 @@ ttyread(void)
|
||||||
if (buflen > 0)
|
if (buflen > 0)
|
||||||
memmove(buf, buf + written, buflen);
|
memmove(buf, buf + written, buflen);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,27 +1106,17 @@ selscroll(int orig, int n)
|
||||||
if (sel.ob.x == -1)
|
if (sel.ob.x == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) {
|
if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) {
|
||||||
if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) {
|
selclear();
|
||||||
|
} else if (BETWEEN(sel.nb.y, orig, term.bot)) {
|
||||||
|
sel.ob.y += n;
|
||||||
|
sel.oe.y += n;
|
||||||
|
if (sel.ob.y < term.top || sel.ob.y > term.bot ||
|
||||||
|
sel.oe.y < term.top || sel.oe.y > term.bot) {
|
||||||
selclear();
|
selclear();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sel.type == SEL_RECTANGULAR) {
|
|
||||||
if (sel.ob.y < term.top)
|
|
||||||
sel.ob.y = term.top;
|
|
||||||
if (sel.oe.y > term.bot)
|
|
||||||
sel.oe.y = term.bot;
|
|
||||||
} else {
|
} else {
|
||||||
if (sel.ob.y < term.top) {
|
selnormalize();
|
||||||
sel.ob.y = term.top;
|
|
||||||
sel.ob.x = 0;
|
|
||||||
}
|
|
||||||
if (sel.oe.y > term.bot) {
|
|
||||||
sel.oe.y = term.bot;
|
|
||||||
sel.oe.x = term.col;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
selnormalize();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1657,6 +1648,12 @@ csihandle(void)
|
||||||
if (csiescseq.arg[0] == 0)
|
if (csiescseq.arg[0] == 0)
|
||||||
ttywrite(vtiden, strlen(vtiden), 0);
|
ttywrite(vtiden, strlen(vtiden), 0);
|
||||||
break;
|
break;
|
||||||
|
case 'b': /* REP -- if last char is printable print it <n> more times */
|
||||||
|
DEFAULT(csiescseq.arg[0], 1);
|
||||||
|
if (term.lastc)
|
||||||
|
while (csiescseq.arg[0]-- > 0)
|
||||||
|
tputc(term.lastc);
|
||||||
|
break;
|
||||||
case 'C': /* CUF -- Cursor <n> Forward */
|
case 'C': /* CUF -- Cursor <n> Forward */
|
||||||
case 'a': /* HPR -- Cursor <n> Forward */
|
case 'a': /* HPR -- Cursor <n> Forward */
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
DEFAULT(csiescseq.arg[0], 1);
|
||||||
|
@ -1780,7 +1777,7 @@ csihandle(void)
|
||||||
break;
|
break;
|
||||||
case 'n': /* DSR – Device Status Report (cursor position) */
|
case 'n': /* DSR – Device Status Report (cursor position) */
|
||||||
if (csiescseq.arg[0] == 6) {
|
if (csiescseq.arg[0] == 6) {
|
||||||
len = snprintf(buf, sizeof(buf),"\033[%i;%iR",
|
len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
|
||||||
term.c.y+1, term.c.x+1);
|
term.c.y+1, term.c.x+1);
|
||||||
ttywrite(buf, len, 0);
|
ttywrite(buf, len, 0);
|
||||||
}
|
}
|
||||||
|
@ -1864,7 +1861,7 @@ strhandle(void)
|
||||||
xsettitle(strescseq.args[1]);
|
xsettitle(strescseq.args[1]);
|
||||||
return;
|
return;
|
||||||
case 52:
|
case 52:
|
||||||
if (narg > 2) {
|
if (narg > 2 && allowwindowops) {
|
||||||
dec = base64dec(strescseq.args[2]);
|
dec = base64dec(strescseq.args[2]);
|
||||||
if (dec) {
|
if (dec) {
|
||||||
xsetsel(dec);
|
xsetsel(dec);
|
||||||
|
@ -2023,7 +2020,7 @@ tdumpline(int n)
|
||||||
bp = &term.line[n][0];
|
bp = &term.line[n][0];
|
||||||
end = &bp[MIN(tlinelen(n), term.col) - 1];
|
end = &bp[MIN(tlinelen(n), term.col) - 1];
|
||||||
if (bp != end || bp->u != ' ') {
|
if (bp != end || bp->u != ' ') {
|
||||||
for ( ;bp <= end; ++bp)
|
for ( ; bp <= end; ++bp)
|
||||||
tprinter(buf, utf8encode(bp->u, buf));
|
tprinter(buf, utf8encode(bp->u, buf));
|
||||||
}
|
}
|
||||||
tprinter("\n", 1);
|
tprinter("\n", 1);
|
||||||
|
@ -2153,6 +2150,7 @@ tcontrolcode(uchar ascii)
|
||||||
return;
|
return;
|
||||||
case '\032': /* SUB */
|
case '\032': /* SUB */
|
||||||
tsetchar('?', &term.c.attr, term.c.x, term.c.y);
|
tsetchar('?', &term.c.attr, term.c.x, term.c.y);
|
||||||
|
/* FALLTHROUGH */
|
||||||
case '\030': /* CAN */
|
case '\030': /* CAN */
|
||||||
csireset();
|
csireset();
|
||||||
break;
|
break;
|
||||||
|
@ -2307,15 +2305,13 @@ tputc(Rune u)
|
||||||
Glyph *gp;
|
Glyph *gp;
|
||||||
|
|
||||||
control = ISCONTROL(u);
|
control = ISCONTROL(u);
|
||||||
if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
|
if (u < 127 || !IS_SET(MODE_UTF8 | MODE_SIXEL)) {
|
||||||
c[0] = u;
|
c[0] = u;
|
||||||
width = len = 1;
|
width = len = 1;
|
||||||
} else {
|
} else {
|
||||||
len = utf8encode(u, c);
|
len = utf8encode(u, c);
|
||||||
if (!control && (width = wcwidth(u)) == -1) {
|
if (!control && (width = wcwidth(u)) == -1)
|
||||||
memcpy(c, "\357\277\275", 4); /* UTF_INVALID */
|
|
||||||
width = 1;
|
width = 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_PRINT))
|
if (IS_SET(MODE_PRINT))
|
||||||
|
@ -2383,6 +2379,8 @@ check_control_code:
|
||||||
/*
|
/*
|
||||||
* control codes are not shown ever
|
* control codes are not shown ever
|
||||||
*/
|
*/
|
||||||
|
if (!term.esc)
|
||||||
|
term.lastc = 0;
|
||||||
return;
|
return;
|
||||||
} else if (term.esc & ESC_START) {
|
} else if (term.esc & ESC_START) {
|
||||||
if (term.esc & ESC_CSI) {
|
if (term.esc & ESC_CSI) {
|
||||||
|
@ -2413,7 +2411,7 @@ check_control_code:
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y))
|
if (selected(term.c.x, term.c.y))
|
||||||
selclear();
|
selclear();
|
||||||
|
|
||||||
gp = &term.line[term.c.y][term.c.x];
|
gp = &term.line[term.c.y][term.c.x];
|
||||||
|
@ -2432,6 +2430,7 @@ check_control_code:
|
||||||
}
|
}
|
||||||
|
|
||||||
tsetchar(u, &term.c.attr, term.c.x, term.c.y);
|
tsetchar(u, &term.c.attr, term.c.x, term.c.y);
|
||||||
|
term.lastc = u;
|
||||||
|
|
||||||
if (width == 2) {
|
if (width == 2) {
|
||||||
gp->mode |= ATTR_WIDE;
|
gp->mode |= ATTR_WIDE;
|
||||||
|
|
1
st.h
1
st.h
|
@ -118,6 +118,7 @@ extern char *stty_args;
|
||||||
extern char *vtiden;
|
extern char *vtiden;
|
||||||
extern wchar_t *worddelimiters;
|
extern wchar_t *worddelimiters;
|
||||||
extern int allowaltscreen;
|
extern int allowaltscreen;
|
||||||
|
extern int allowwindowops;
|
||||||
extern char *termname;
|
extern char *termname;
|
||||||
extern unsigned int tabspaces;
|
extern unsigned int tabspaces;
|
||||||
extern unsigned int defaultfg;
|
extern unsigned int defaultfg;
|
||||||
|
|
3
st.info
3
st.info
|
@ -158,6 +158,7 @@ st-mono| simpleterm monocolor,
|
||||||
rc=\E8,
|
rc=\E8,
|
||||||
rev=\E[7m,
|
rev=\E[7m,
|
||||||
ri=\EM,
|
ri=\EM,
|
||||||
|
rin=\E[%p1%dT,
|
||||||
ritm=\E[23m,
|
ritm=\E[23m,
|
||||||
rmacs=\E(B,
|
rmacs=\E(B,
|
||||||
rmcup=\E[?1049l,
|
rmcup=\E[?1049l,
|
||||||
|
@ -183,6 +184,8 @@ st-mono| simpleterm monocolor,
|
||||||
# XTerm extensions
|
# XTerm extensions
|
||||||
rmxx=\E[29m,
|
rmxx=\E[29m,
|
||||||
smxx=\E[9m,
|
smxx=\E[9m,
|
||||||
|
# disabled rep for now: causes some issues with older ncurses versions.
|
||||||
|
# rep=%p1%c\E[%p2%{1}%-%db,
|
||||||
# tmux extensions, see TERMINFO EXTENSIONS in tmux(1)
|
# tmux extensions, see TERMINFO EXTENSIONS in tmux(1)
|
||||||
Tc,
|
Tc,
|
||||||
Ms=\E]52;%p1%s;%p2%s\007,
|
Ms=\E]52;%p1%s;%p2%s\007,
|
||||||
|
|
130
x.c
130
x.c
|
@ -1526,8 +1526,9 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
||||||
/* draw the new one */
|
/* draw the new one */
|
||||||
if (IS_SET(MODE_FOCUSED)) {
|
if (IS_SET(MODE_FOCUSED)) {
|
||||||
switch (win.cursor) {
|
switch (win.cursor) {
|
||||||
case 7: /* st extension: snowman (U+2603) */
|
case 7: /* st extension */
|
||||||
g.u = 0x2603;
|
g.u = 0x2603; /* snowman (U+2603) */
|
||||||
|
/* FALLTHROUGH */
|
||||||
case 0: /* Blinking Block */
|
case 0: /* Blinking Block */
|
||||||
case 1: /* Blinking Block (Default) */
|
case 1: /* Blinking Block (Default) */
|
||||||
case 2: /* Steady Block */
|
case 2: /* Steady Block */
|
||||||
|
@ -1689,8 +1690,7 @@ xsetmode(int set, unsigned int flags)
|
||||||
int
|
int
|
||||||
xsetcursor(int cursor)
|
xsetcursor(int cursor)
|
||||||
{
|
{
|
||||||
DEFAULT(cursor, 1);
|
if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
|
||||||
if (!BETWEEN(cursor, 0, 6))
|
|
||||||
return 1;
|
return 1;
|
||||||
win.cursor = cursor;
|
win.cursor = cursor;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1867,10 +1867,9 @@ run(void)
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
int w = win.w, h = win.h;
|
int w = win.w, h = win.h;
|
||||||
fd_set rfd;
|
fd_set rfd;
|
||||||
int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
|
int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing;
|
||||||
int ttyfd;
|
struct timespec seltv, *tv, now, lastblink, trigger;
|
||||||
struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
|
double timeout;
|
||||||
long deltatime;
|
|
||||||
|
|
||||||
/* Waiting for window mapping */
|
/* Waiting for window mapping */
|
||||||
do {
|
do {
|
||||||
|
@ -1891,82 +1890,77 @@ run(void)
|
||||||
ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
|
ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
|
||||||
cresize(w, h);
|
cresize(w, h);
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &last);
|
for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) {
|
||||||
lastblink = last;
|
|
||||||
|
|
||||||
for (xev = actionfps;;) {
|
|
||||||
FD_ZERO(&rfd);
|
FD_ZERO(&rfd);
|
||||||
FD_SET(ttyfd, &rfd);
|
FD_SET(ttyfd, &rfd);
|
||||||
FD_SET(xfd, &rfd);
|
FD_SET(xfd, &rfd);
|
||||||
|
|
||||||
|
if (XPending(xw.dpy))
|
||||||
|
timeout = 0; /* existing events might not set xfd */
|
||||||
|
|
||||||
|
seltv.tv_sec = timeout / 1E3;
|
||||||
|
seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec);
|
||||||
|
tv = timeout >= 0 ? &seltv : NULL;
|
||||||
|
|
||||||
if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
|
if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
die("select failed: %s\n", strerror(errno));
|
die("select failed: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
if (FD_ISSET(ttyfd, &rfd)) {
|
|
||||||
ttyread();
|
|
||||||
if (blinktimeout) {
|
|
||||||
blinkset = tattrset(ATTR_BLINK);
|
|
||||||
if (!blinkset)
|
|
||||||
MODBIT(win.mode, 0, MODE_BLINK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(xfd, &rfd))
|
|
||||||
xev = actionfps;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
drawtimeout.tv_sec = 0;
|
|
||||||
drawtimeout.tv_nsec = (1000 * 1E6)/ xfps;
|
|
||||||
tv = &drawtimeout;
|
|
||||||
|
|
||||||
dodraw = 0;
|
if (FD_ISSET(ttyfd, &rfd))
|
||||||
if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
|
ttyread();
|
||||||
tsetdirtattr(ATTR_BLINK);
|
|
||||||
win.mode ^= MODE_BLINK;
|
xev = 0;
|
||||||
lastblink = now;
|
while (XPending(xw.dpy)) {
|
||||||
dodraw = 1;
|
xev = 1;
|
||||||
}
|
XNextEvent(xw.dpy, &ev);
|
||||||
deltatime = TIMEDIFF(now, last);
|
if (XFilterEvent(&ev, None))
|
||||||
if (deltatime > 1000 / (xev ? xfps : actionfps)) {
|
continue;
|
||||||
dodraw = 1;
|
if (handler[ev.type])
|
||||||
last = now;
|
(handler[ev.type])(&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dodraw) {
|
/*
|
||||||
while (XPending(xw.dpy)) {
|
* To reduce flicker and tearing, when new content or event
|
||||||
XNextEvent(xw.dpy, &ev);
|
* triggers drawing, we first wait a bit to ensure we got
|
||||||
if (XFilterEvent(&ev, None))
|
* everything, and if nothing new arrives - we draw.
|
||||||
continue;
|
* We start with trying to wait minlatency ms. If more content
|
||||||
if (handler[ev.type])
|
* arrives sooner, we retry with shorter and shorter periods,
|
||||||
(handler[ev.type])(&ev);
|
* and eventually draw even without idle after maxlatency ms.
|
||||||
|
* Typically this results in low latency while interacting,
|
||||||
|
* 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 (!drawing) {
|
||||||
|
trigger = now;
|
||||||
|
drawing = 1;
|
||||||
}
|
}
|
||||||
|
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
|
||||||
|
/ maxlatency * minlatency;
|
||||||
|
if (timeout > 0)
|
||||||
|
continue; /* we have time, try to find idle */
|
||||||
|
}
|
||||||
|
|
||||||
draw();
|
/* idle detected or maxlatency exhausted -> draw */
|
||||||
XFlush(xw.dpy);
|
timeout = -1;
|
||||||
|
if (blinktimeout && tattrset(ATTR_BLINK)) {
|
||||||
if (xev && !FD_ISSET(xfd, &rfd))
|
timeout = blinktimeout - TIMEDIFF(now, lastblink);
|
||||||
xev--;
|
if (timeout <= 0) {
|
||||||
if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) {
|
if (-timeout > blinktimeout) /* start visible */
|
||||||
if (blinkset) {
|
win.mode |= MODE_BLINK;
|
||||||
if (TIMEDIFF(now, lastblink) \
|
win.mode ^= MODE_BLINK;
|
||||||
> blinktimeout) {
|
tsetdirtattr(ATTR_BLINK);
|
||||||
drawtimeout.tv_nsec = 1000;
|
lastblink = now;
|
||||||
} else {
|
timeout = blinktimeout;
|
||||||
drawtimeout.tv_nsec = (1E6 * \
|
|
||||||
(blinktimeout - \
|
|
||||||
TIMEDIFF(now,
|
|
||||||
lastblink)));
|
|
||||||
}
|
|
||||||
drawtimeout.tv_sec = \
|
|
||||||
drawtimeout.tv_nsec / 1E9;
|
|
||||||
drawtimeout.tv_nsec %= (long)1E9;
|
|
||||||
} else {
|
|
||||||
tv = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw();
|
||||||
|
XFlush(xw.dpy);
|
||||||
|
drawing = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1988,7 +1982,7 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
xw.l = xw.t = 0;
|
xw.l = xw.t = 0;
|
||||||
xw.isfixed = False;
|
xw.isfixed = False;
|
||||||
win.cursor = cursorshape;
|
xsetcursor(cursorshape);
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'a':
|
case 'a':
|
||||||
|
|
Loading…
Reference in a new issue