aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDylan Araps <dylan.araps@gmail.com>2026-02-28 09:35:10 +0200
committerDylan Araps <dylan.araps@gmail.com>2026-02-28 09:35:10 +0200
commitf700440f9ca9be7dd6e5615b3a84c1c9e1ca18c2 (patch)
tree6941e2d48c3b2c5f3c2a2f9b0c730a6d75d0b199 /lib
parentfc339fa3cb9c03fdebd300f7018b23931a3eb7bd (diff)
dfm: also wake on winch
This adds responsive resize whilst still allowing dfm to do nothing at idle. Nifty.
Diffstat (limited to 'lib')
-rw-r--r--lib/term.h52
1 files changed, 36 insertions, 16 deletions
diff --git a/lib/term.h b/lib/term.h
index 4c0c2c5..3b35ade 100644
--- a/lib/term.h
+++ b/lib/term.h
@@ -23,6 +23,7 @@
#define DYLAN_TERM_H
#include <assert.h>
+#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
@@ -36,8 +37,9 @@
#include "vt.h"
enum {
- TERM_LOADED = 1 << 0,
- TERM_RESIZE = 1 << 1,
+ TERM_LOADED = 1 << 0,
+ TERM_WAIT_WCH = 1 << 1,
+ TERM_WAIT_KEY = 1 << 2,
};
static struct term {
@@ -45,6 +47,7 @@ static struct term {
int fd;
int null;
volatile sig_atomic_t flag;
+ volatile sig_atomic_t resize;
volatile sig_atomic_t dead;
} *TERM;
@@ -60,12 +63,6 @@ term_dead(const struct term *t)
return t->dead;
}
-static inline int
-term_resize(const struct term *t)
-{
- return t->flag & TERM_RESIZE;
-}
-
static inline void
term_restore_on_signal(int s)
{
@@ -105,7 +102,7 @@ static inline void
term_signal_sigwinch(int s)
{
(void) s;
- if (TERM) TERM->flag |= TERM_RESIZE;
+ if (TERM) TERM->resize = 1;
}
static inline void
@@ -123,6 +120,7 @@ term_signal_setup(void) {
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
+ sa.sa_flags = 0;
sa.sa_handler = term_signal_sigwinch;
sigaction(SIGWINCH, &sa, NULL);
}
@@ -130,13 +128,15 @@ term_signal_setup(void) {
static inline int
term_size_update(struct term *t, u16 *row, u16 *col)
{
- struct winsize ws;
- if (ioctl(t->fd, TIOCGWINSZ, &ws) < 0)
- return -1;
- t->flag &= ~TERM_RESIZE;
- *row = ws.ws_row;
- *col = ws.ws_col;
- return 0;
+ for (;;) {
+ t->resize = 0;
+ struct winsize ws;
+ if (ioctl(t->fd, TIOCGWINSZ, &ws) < 0)
+ return -1;
+ *row = ws.ws_row;
+ *col = ws.ws_col;
+ if (!t->resize) return 0;
+ }
}
static inline int
@@ -192,6 +192,26 @@ term_reap(void)
for (int st; waitpid(-1, &st, WNOHANG) > 0; );
}
+static inline int
+term_wait(struct term *t)
+{
+ for (;;) {
+ if (t->resize) return TERM_WAIT_WCH;
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(t->fd, &rfds);
+ int r = select(t->fd + 1, &rfds, NULL, NULL, NULL);
+ if (r < 0) {
+ if (errno != EINTR) return 0;
+ if (t->resize) return TERM_WAIT_WCH;
+ continue;
+ }
+ if (FD_ISSET(t->fd, &rfds))
+ return TERM_WAIT_KEY;
+ return 0;
+ }
+}
+
static inline void
term_destroy(const struct term *t)
{