From f700440f9ca9be7dd6e5615b3a84c1c9e1ca18c2 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 28 Feb 2026 09:35:10 +0200 Subject: dfm: also wake on winch This adds responsive resize whilst still allowing dfm to do nothing at idle. Nifty. --- README.txt | 4 ---- dfm.c | 10 ++++++---- lib/term.h | 52 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/README.txt b/README.txt index 37a21dd..1256f70 100644 --- a/README.txt +++ b/README.txt @@ -371,10 +371,6 @@ See the config_key.h.in and config_cmd.h.in files for more information. DESIGN CONSIDERATIONS ________________________________________________________________________________ -* I wanted DFM to do absolutely nothing when idle so SIGWINCH (resize handling) - will not automatically perform a size adjustment and redraw until the next - keypress. - * I employed many tricks in order to keep memory usage low whilst still allowing for fast operations and relatively large directory trees. diff --git a/dfm.c b/dfm.c index f6a30dc..695b0aa 100644 --- a/dfm.c +++ b/dfm.c @@ -3342,9 +3342,6 @@ static inline void fm_update(struct fm *p) { term_reap(); - if (unlikely(term_resize(&p->t))) - if (fm_term_resize(p) < 0) - fm_draw_err(p, S("resize failed"), errno); fm_watch_handle(p); if (!(p->f & FM_DIRTY)) return; p->f &= ~FM_DIRTY; @@ -3403,7 +3400,12 @@ fm_run(struct fm *p) for (; likely(!term_dead(&p->t)); ) { fm_update(p); fm_draw(p); - fm_input(p); + int e = term_wait(&p->t); + if (e & TERM_WAIT_WCH) + if (fm_term_resize(p) < 0) + fm_draw_err(p, S("resize failed"), errno); + if (e & TERM_WAIT_KEY) + fm_input(p); } fm_term_free(p); if (!(p->f & FM_PRINT_PWD)) p->pwd.l = 0; 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 +#include #include #include #include @@ -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) { -- cgit v1.2.3