diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e849bae..31ec70c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,6 +95,10 @@ means foot can be PGO:d in e.g. sandboxed build scripts. See * Graphical glitches/flashes when resizing the window while running a fullscreen application, i.e. the 'alt' screen (https://codeberg.org/dnkl/foot/issues/221). +* Cursor will now blink if **either** `CSI ? 12 h` or `CSI Ps SP q` + has been used to enable blinking. **cursor.blink** in `foot.ini` + controls the default state of `CSI Ps SP q` + (https://codeberg.org/dnkl/foot/issues/218). ### Deprecated diff --git a/csi.c b/csi.c index 80f2bfd0..e4975583 100644 --- a/csi.c +++ b/csi.c @@ -15,6 +15,7 @@ #define LOG_MODULE "csi" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "config.h" #include "grid.h" #include "selection.h" #include "sixel.h" @@ -389,10 +390,8 @@ decset_decrst(struct terminal *term, unsigned param, bool enable) break; case 12: - if (enable) - term_cursor_blink_enable(term); - else - term_cursor_blink_disable(term); + term->cursor_blink.decset = enable; + term_cursor_blink_update(term); break; case 25: @@ -555,12 +554,6 @@ decrst(struct terminal *term, unsigned param) decset_decrst(term, param, false); } -static bool -timespecs_equal(const struct timespec *a, const struct timespec *b) -{ - return a->tv_sec == b->tv_sec && a->tv_nsec == b->tv_nsec; -} - static void xtsave(struct terminal *term, unsigned param) { @@ -572,20 +565,7 @@ xtsave(struct terminal *term, unsigned param) case 6: term->xtsave.origin = term->origin; break; case 7: term->xtsave.auto_margin = term->auto_margin; break; case 9: /* term->xtsave.mouse_x10 = term->mouse_tracking == MOUSE_X10; */ break; - - case 12: { - struct itimerspec current_value; - if (timerfd_gettime(term->cursor_blink.fd, ¤t_value) < 0) - LOG_WARN("xtsave: failed to read cursor blink timer: %s", strerror(errno)); - else { - const struct timespec zero = {.tv_sec = 0, .tv_nsec = 0}; - term->xtsave.cursor_blink = - !(timespecs_equal(¤t_value.it_interval, &zero) && - timespecs_equal(¤t_value.it_value, &zero)); - } - break; - } - + case 12: term->xtsave.cursor_blink = term->cursor_blink.decset; break; case 25: term->xtsave.show_cursor = !term->hide_cursor; break; case 45: term->xtsave.reverse_wrap = term->reverse_wrap; break; case 1000: term->xtsave.mouse_click = term->mouse_tracking == MOUSE_CLICK; break; @@ -1513,11 +1493,9 @@ csi_dispatch(struct terminal *term, uint8_t final) int param = vt_param_get(term, 0, 0); switch (param) { case 0: /* blinking block, but we use it to reset to configured default */ - term->cursor_style = term->default_cursor_style; - if (term->default_cursor_blink) - term_cursor_blink_enable(term); - else - term_cursor_blink_disable(term); + term->cursor_style = term->conf->cursor.style; + term->cursor_blink.deccsusr = term->conf->cursor.blink; + term_cursor_blink_update(term); break; case 1: /* blinking block */ @@ -1541,10 +1519,8 @@ csi_dispatch(struct terminal *term, uint8_t final) } if (param > 0 && param <= 6) { - if (param & 1) - term_cursor_blink_enable(term); - else - term_cursor_blink_disable(term); + term->cursor_blink.deccsusr = param & 1; + term_cursor_blink_update(term); } break; } diff --git a/osc.c b/osc.c index bf0fff7e..f89becfd 100644 --- a/osc.c +++ b/osc.c @@ -8,6 +8,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "base64.h" +#include "config.h" #include "grid.h" #include "render.h" #include "selection.h" @@ -663,8 +664,8 @@ osc_dispatch(struct terminal *term) case 112: LOG_DBG("resetting cursor color"); - term->cursor_color.text = term->default_cursor_color.text; - term->cursor_color.cursor = term->default_cursor_color.cursor; + term->cursor_color.text = term->conf->cursor.color.text; + term->cursor_color.cursor = term->conf->cursor.color.cursor; term_damage_cursor(term); break; diff --git a/terminal.c b/terminal.c index 349fd9bf..6a20056c 100644 --- a/terminal.c +++ b/terminal.c @@ -198,6 +198,8 @@ fdm_ptmx_out(struct fdm *fdm, int fd, int events, void *data) static struct timespec last = {0}; #endif +static bool cursor_blink_rearm_timer(struct terminal *term); + /* Externally visible, but not declared in terminal.h, to enable pgo * to call this function directly */ bool @@ -215,7 +217,10 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) } /* Prevent blinking while typing */ - term_cursor_blink_restart(term); + if (term->cursor_blink.fd >= 0) { + term->cursor_blink.state = CURSOR_BLINK_ON; + cursor_blink_rearm_timer(term); + } term->render.app_sync_updates.flipped = false; @@ -311,7 +316,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) } if (hup) { - if (term->hold_at_exit) { + if (term->conf->hold_at_exit) { fdm_del(fdm, fd); term->ptmx = -1; return true; @@ -1056,18 +1061,13 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .alpha = conf->colors.alpha, }, .origin = ORIGIN_ABSOLUTE, - .default_cursor_blink = conf->cursor.blink, - .default_cursor_style = conf->cursor.style, .cursor_style = conf->cursor.style, .cursor_blink = { - .active = conf->cursor.blink, + .decset = false, + .deccsusr = conf->cursor.blink, .state = CURSOR_BLINK_ON, .fd = -1, }, - .default_cursor_color = { - .text = conf->cursor.color.text, - .cursor = conf->cursor.color.cursor, - }, .cursor_color = { .text = conf->cursor.color.text, .cursor = conf->cursor.color.cursor, @@ -1112,7 +1112,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .max_width = SIXEL_MAX_WIDTH, .max_height = SIXEL_MAX_HEIGHT, }, - .hold_at_exit = conf->hold_at_exit, .shutdown_cb = shutdown_cb, .shutdown_data = shutdown_data, .foot_exe = xstrdup(foot_exe), @@ -1256,13 +1255,13 @@ term_shutdown(struct terminal *term) * iteration, by creating an event FD that we trigger immediately. */ - term_cursor_blink_disable(term); + term_cursor_blink_update(term); + assert(term->cursor_blink.fd < 0); fdm_del(term->fdm, term->selection.auto_scroll.fd); fdm_del(term->fdm, term->render.app_sync_updates.timer_fd); fdm_del(term->fdm, term->delayed_render_timer.lower_fd); fdm_del(term->fdm, term->delayed_render_timer.upper_fd); - fdm_del(term->fdm, term->cursor_blink.fd); fdm_del(term->fdm, term->blink.fd); fdm_del(term->fdm, term->flash.fd); @@ -1275,7 +1274,6 @@ term_shutdown(struct terminal *term) term->render.app_sync_updates.timer_fd = -1; term->delayed_render_timer.lower_fd = -1; term->delayed_render_timer.upper_fd = -1; - term->cursor_blink.fd = -1; term->blink.fd = -1; term->flash.fd = -1; term->ptmx = -1; @@ -1575,13 +1573,12 @@ term_reset(struct terminal *term, bool hard) term->normal.saved_cursor = (struct cursor){.point = {0, 0}}; term->alt.cursor = (struct cursor){.point = {0, 0}}; term->alt.saved_cursor = (struct cursor){.point = {0, 0}}; - term->cursor_style = term->default_cursor_style; - if (term->conf->cursor.blink) - term_cursor_blink_enable(term); - else - term_cursor_blink_disable(term); - term->cursor_color.text = term->default_cursor_color.text; - term->cursor_color.cursor = term->default_cursor_color.cursor; + term->cursor_style = term->conf->cursor.style; + term->cursor_blink.decset = false; + term->cursor_blink.deccsusr = term->conf->cursor.blink; + term_cursor_blink_update(term); + term->cursor_color.text = term->conf->cursor.color.text; + term->cursor_color.cursor = term->conf->cursor.color.cursor; selection_cancel(term); term->normal.offset = term->normal.view = 0; term->alt.offset = term->alt.view = 0; @@ -1917,7 +1914,7 @@ term_cursor_down(struct terminal *term, int count) } static bool -cursor_blink_start_timer(struct terminal *term) +cursor_blink_rearm_timer(struct terminal *term) { if (term->cursor_blink.fd < 0) { int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); @@ -1950,7 +1947,7 @@ cursor_blink_start_timer(struct terminal *term) } static bool -cursor_blink_stop_timer(struct terminal *term) +cursor_blink_disarm_timer(struct terminal *term) { fdm_del(term->fdm, term->cursor_blink.fd); term->cursor_blink.fd = -1; @@ -1958,29 +1955,21 @@ cursor_blink_stop_timer(struct terminal *term) } void -term_cursor_blink_enable(struct terminal *term) +term_cursor_blink_update(struct terminal *term) { - term->cursor_blink.state = CURSOR_BLINK_ON; - term->cursor_blink.active = term->kbd_focus - ? cursor_blink_start_timer(term) : true; -} + bool enable = term->cursor_blink.decset || term->cursor_blink.deccsusr; + bool activate = !term->is_shutting_down && enable && term->kbd_focus; -void -term_cursor_blink_disable(struct terminal *term) -{ - term->cursor_blink.active = false; - term->cursor_blink.state = CURSOR_BLINK_ON; - cursor_blink_stop_timer(term); -} + LOG_DBG("decset=%d, deccsrusr=%d, focus=%d, shutting-down=%d, enable=%d, activate=%d", + term->cursor_blink.decset, term->cursor_blink.deccsusr, + term->kbd_focus, term->is_shutting_down, + enable, activate); -void -term_cursor_blink_restart(struct terminal *term) -{ - if (term->cursor_blink.active) { + if (activate && term->cursor_blink.fd < 0) { term->cursor_blink.state = CURSOR_BLINK_ON; - term->cursor_blink.active = term->kbd_focus - ? cursor_blink_start_timer(term) : true; - } + cursor_blink_rearm_timer(term); + } else if (!activate && term->cursor_blink.fd >= 0) + cursor_blink_disarm_timer(term); } static bool @@ -2182,9 +2171,7 @@ term_visual_focus_in(struct terminal *term) return; term->visual_focus = true; - if (term->cursor_blink.active) - cursor_blink_start_timer(term); - + term_cursor_blink_update(term); render_refresh_csd(term); } @@ -2195,9 +2182,7 @@ term_visual_focus_out(struct terminal *term) return; term->visual_focus = false; - if (term->cursor_blink.active) - cursor_blink_stop_timer(term); - + term_cursor_blink_update(term); render_refresh_csd(term); } diff --git a/terminal.h b/terminal.h index 513dfcab..ea49edf2 100644 --- a/terminal.h +++ b/terminal.h @@ -336,18 +336,13 @@ struct terminal { uint32_t default_table[256]; } colors; - enum cursor_style default_cursor_style; enum cursor_style cursor_style; struct { - bool active; - enum { CURSOR_BLINK_ON, CURSOR_BLINK_OFF } state; + bool decset; /* Blink enabled via '\E[?12h' */ + bool deccsusr; /* Blink enabled via '\E[X q' */ int fd; + enum { CURSOR_BLINK_ON, CURSOR_BLINK_OFF } state; } cursor_blink; - bool default_cursor_blink; - struct { - uint32_t text; - uint32_t cursor; - } default_cursor_color; struct { uint32_t text; uint32_t cursor; @@ -474,7 +469,6 @@ struct terminal { } sixel; bool quit; - bool hold_at_exit; bool is_shutting_down; void (*shutdown_cb)(void *data, int exit_code); void *shutdown_data; @@ -544,9 +538,7 @@ void term_cursor_left(struct terminal *term, int count); void term_cursor_right(struct terminal *term, int count); void term_cursor_up(struct terminal *term, int count); void term_cursor_down(struct terminal *term, int count); -void term_cursor_blink_enable(struct terminal *term); -void term_cursor_blink_disable(struct terminal *term); -void term_cursor_blink_restart(struct terminal *term); +void term_cursor_blink_update(struct terminal *term); void term_print(struct terminal *term, wchar_t wc, int width);