aboutsummaryrefslogtreecommitdiff
path: root/.repos/st/x.c
diff options
context:
space:
mode:
Diffstat (limited to '.repos/st/x.c')
-rw-r--r--.repos/st/x.c154
1 files changed, 83 insertions, 71 deletions
diff --git a/.repos/st/x.c b/.repos/st/x.c
index c09392b..55f4a61 100644
--- a/.repos/st/x.c
+++ b/.repos/st/x.c
@@ -661,8 +661,6 @@ setsel(char *str, Time t)
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
selclear();
-
- clipcopy(NULL);
}
void
@@ -680,7 +678,7 @@ brelease(XEvent *e)
}
if (e->xbutton.button == Button2)
- clippaste(NULL);
+ selpaste(NULL);
else if (e->xbutton.button == Button1)
mousesel(e, 1);
}
@@ -816,6 +814,8 @@ xsetcolorname(int x, const char *name)
XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
dc.col[x] = ncolor;
+ if (x == defaultbg)
+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
return 0;
}
@@ -832,6 +832,13 @@ xclear(int x1, int y1, int x2, int y2)
}
void
+xclearwin(void)
+{
+ xclear(0, 0, win.w, win.h);
+}
+
+
+void
xhints(void)
{
XClassHint class = {opt_name ? opt_name : "st",
@@ -1296,6 +1303,8 @@ xinit(int cols, int rows)
xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
if (xsel.xtarget == None)
xsel.xtarget = XA_STRING;
+
+ boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis);
}
int
@@ -1342,8 +1351,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
yp = winy + font->ascent + win.cyo;
}
- /* Lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ if (mode & ATTR_BOXDRAW) {
+ /* minor shoehorning: boxdraw uses only this ushort */
+ glyphidx = boxdrawindex(&glyphs[i]);
+ } else {
+ /* Lookup character index with default font. */
+ glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ }
if (glyphidx) {
specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx;
@@ -1543,8 +1557,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
r.width = width;
XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ if (base.mode & ATTR_BOXDRAW) {
+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
+ } else {
+ /* Render the glyphs. */
+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ }
/* Render underline and strikethrough. */
if (base.mode & ATTR_UNDERLINE) {
@@ -1587,7 +1605,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
/*
* Select the right color for the right mode.
*/
- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE;
+ g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW;
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
@@ -1947,10 +1965,9 @@ run(void)
XEvent ev;
int w = win.w, h = win.h;
fd_set rfd;
- int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
- int ttyfd;
- struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
- long deltatime;
+ int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing;
+ struct timespec seltv, *tv, now, lastblink, trigger;
+ double timeout;
/* Waiting for window mapping */
do {
@@ -1971,82 +1988,77 @@ run(void)
ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
cresize(w, h);
- clock_gettime(CLOCK_MONOTONIC, &last);
- lastblink = last;
-
- for (xev = actionfps;;) {
+ for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) {
FD_ZERO(&rfd);
FD_SET(ttyfd, &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 (errno == EINTR)
continue;
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);
- }
- }
+ clock_gettime(CLOCK_MONOTONIC, &now);
- if (FD_ISSET(xfd, &rfd))
- xev = actionfps;
+ if (FD_ISSET(ttyfd, &rfd))
+ ttyread();
- clock_gettime(CLOCK_MONOTONIC, &now);
- drawtimeout.tv_sec = 0;
- drawtimeout.tv_nsec = (1000 * 1E6)/ xfps;
- tv = &drawtimeout;
-
- dodraw = 0;
- if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
- tsetdirtattr(ATTR_BLINK);
- win.mode ^= MODE_BLINK;
- lastblink = now;
- dodraw = 1;
- }
- deltatime = TIMEDIFF(now, last);
- if (deltatime > 1000 / (xev ? xfps : actionfps)) {
- dodraw = 1;
- last = now;
+ xev = 0;
+ while (XPending(xw.dpy)) {
+ xev = 1;
+ XNextEvent(xw.dpy, &ev);
+ if (XFilterEvent(&ev, None))
+ continue;
+ if (handler[ev.type])
+ (handler[ev.type])(&ev);
}
- if (dodraw) {
- while (XPending(xw.dpy)) {
- XNextEvent(xw.dpy, &ev);
- if (XFilterEvent(&ev, None))
- continue;
- if (handler[ev.type])
- (handler[ev.type])(&ev);
+ /*
+ * To reduce flicker and tearing, when new content or event
+ * triggers drawing, we first wait a bit to ensure we got
+ * everything, and if nothing new arrives - we draw.
+ * We start with trying to wait minlatency ms. If more content
+ * arrives sooner, we retry with shorter and shorter preiods,
+ * 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();
- XFlush(xw.dpy);
-
- if (xev && !FD_ISSET(xfd, &rfd))
- xev--;
- if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) {
- if (blinkset) {
- if (TIMEDIFF(now, lastblink) \
- > blinktimeout) {
- drawtimeout.tv_nsec = 1000;
- } else {
- drawtimeout.tv_nsec = (1E6 * \
- (blinktimeout - \
- TIMEDIFF(now,
- lastblink)));
- }
- drawtimeout.tv_sec = \
- drawtimeout.tv_nsec / 1E9;
- drawtimeout.tv_nsec %= (long)1E9;
- } else {
- tv = NULL;
- }
+ /* idle detected or maxlatency exhausted -> draw */
+ timeout = -1;
+ if (blinktimeout && tattrset(ATTR_BLINK)) {
+ timeout = blinktimeout - TIMEDIFF(now, lastblink);
+ if (timeout <= 0) {
+ if (-timeout > blinktimeout) /* start visible */
+ win.mode |= MODE_BLINK;
+ win.mode ^= MODE_BLINK;
+ tsetdirtattr(ATTR_BLINK);
+ lastblink = now;
+ timeout = blinktimeout;
}
}
+
+ draw();
+ XFlush(xw.dpy);
+ drawing = 0;
}
}