From c4f13809430e7086fb6a0f2c80930a7537c7175d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 20 May 2024 09:03:29 +0200 Subject: [PATCH] config: add cursor.blink-rate option The default is 500ms, which corresponds to the old, hardcoded default. Closes #1707 --- CHANGELOG.md | 7 +++++++ config.c | 10 ++++++++-- config.h | 5 ++++- csi.c | 2 +- doc/foot.ini.5.scd | 7 ++++++- terminal.c | 14 +++++++++----- tests/test-config.c | 3 ++- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10ec7463..45b58778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,13 @@ ## Unreleased ### Added + +* `cursor.blink-rate` option, allowing you to configure the rate the + cursor blinks with (when `cursor.blink=yes`) ([#1707][1707]); + +[1707]: https://codeberg.org/dnkl/foot/issues/1707 + + ### Changed * All `XTGETTCAP` capabilities are now in the `tigetstr()` format: diff --git a/config.c b/config.c index d63934b3..b7bc1f09 100644 --- a/config.c +++ b/config.c @@ -1395,7 +1395,10 @@ parse_section_cursor(struct context *ctx) } else if (streq(key, "blink")) - return value_to_bool(ctx, &conf->cursor.blink); + return value_to_bool(ctx, &conf->cursor.blink.enabled); + + else if (streq(key, "blink-rate")) + return value_to_uint32(ctx, 10, &conf->cursor.blink.rate_ms); else if (streq(key, "color")) { if (!value_to_two_colors( @@ -3102,7 +3105,10 @@ config_load(struct config *conf, const char *conf_path, .cursor = { .style = CURSOR_BLOCK, .unfocused_style = CURSOR_UNFOCUSED_HOLLOW, - .blink = false, + .blink = { + .enabled = false, + .rate_ms = 500, + }, .color = { .text = 0, .cursor = 0, diff --git a/config.h b/config.h index df3d45f9..e2d94507 100644 --- a/config.h +++ b/config.h @@ -262,7 +262,10 @@ struct config { struct { enum cursor_style style; enum cursor_unfocused_style unfocused_style; - bool blink; + struct { + bool enabled; + uint32_t rate_ms; + } blink; struct { uint32_t text; uint32_t cursor; diff --git a/csi.c b/csi.c index 04777310..3e044908 100644 --- a/csi.c +++ b/csi.c @@ -1665,7 +1665,7 @@ csi_dispatch(struct terminal *term, uint8_t final) switch (param) { case 0: /* blinking block, but we use it to reset to configured default */ term->cursor_style = term->conf->cursor.style; - term->cursor_blink.deccsusr = term->conf->cursor.blink; + term->cursor_blink.deccsusr = term->conf->cursor.blink.enabled; term_cursor_blink_update(term); break; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index a3ddb7c3..93a3120c 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -511,7 +511,12 @@ applications can change these at runtime. *blink* Boolean. Enables blinking cursor. Note that this can be overridden - by applications. Default: _no_. + by applications. Related option: *blink-rate*. Default: _no_. + +*blink-rate* + The rate at which the cursor blink, when cursor blinking has been + enabled. Expressed in milliseconds between each blink. Default: + _500_. *color* Two space separated RRGGBB values (i.e. plain old 6-digit hex diff --git a/terminal.c b/terminal.c index b684030e..9443467c 100644 --- a/terminal.c +++ b/terminal.c @@ -1229,7 +1229,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .cursor_style = conf->cursor.style, .cursor_blink = { .decset = false, - .deccsusr = conf->cursor.blink, + .deccsusr = conf->cursor.blink.enabled, .state = CURSOR_BLINK_ON, .fd = -1, }, @@ -2046,7 +2046,7 @@ term_reset(struct terminal *term, bool hard) term->alt.saved_cursor = (struct cursor){.point = {0, 0}}; term->cursor_style = term->conf->cursor.style; term->cursor_blink.decset = false; - term->cursor_blink.deccsusr = term->conf->cursor.blink; + term->cursor_blink.deccsusr = term->conf->cursor.blink.enabled; term_cursor_blink_update(term); term->cursor_color.text = term->conf->cursor.color.text; term->cursor_color.cursor = term->conf->cursor.color.cursor; @@ -2746,9 +2746,13 @@ cursor_blink_rearm_timer(struct terminal *term) term->cursor_blink.fd = fd; } - static const struct itimerspec timer = { - .it_value = {.tv_sec = 0, .tv_nsec = 500000000}, - .it_interval = {.tv_sec = 0, .tv_nsec = 500000000}, + const int rate_ms = term->conf->cursor.blink.rate_ms; + const long secs = rate_ms / 1000; + const long nsecs = (rate_ms % 1000) * 1000000; + + const struct itimerspec timer = { + .it_value = {.tv_sec = secs, .tv_nsec = nsecs}, + .it_interval = {.tv_sec = secs, .tv_nsec = nsecs}, }; if (timerfd_settime(term->cursor_blink.fd, 0, &timer, NULL) < 0) { diff --git a/tests/test-config.c b/tests/test-config.c index 3d4d345c..4a0fd755 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -641,7 +641,8 @@ test_section_cursor(void) (const char *[]){"unchanged", "hollow", "none"}, (int []){CURSOR_UNFOCUSED_UNCHANGED, CURSOR_UNFOCUSED_HOLLOW, CURSOR_UNFOCUSED_NONE}, (int *)&conf.cursor.unfocused_style); - test_boolean(&ctx, &parse_section_cursor, "blink", &conf.cursor.blink); + test_boolean(&ctx, &parse_section_cursor, "blink", &conf.cursor.blink.enabled); + test_uint32(&ctx, &parse_section_cursor, "blink-rate", &conf.cursor.blink.rate_ms); test_pt_or_px(&ctx, &parse_section_cursor, "beam-thickness", &conf.cursor.beam_thickness); test_pt_or_px(&ctx, &parse_section_cursor, "underline-thickness",