diff --git a/CHANGELOG.md b/CHANGELOG.md index f555d472..3d824c2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,13 @@ ## Unreleased ### Added + +* `cursor.unfocused-style=unchanged|hollow|none` to `foot.ini`. The + default is `hollow` ([#1582][1582]). + +[1582]: https://codeberg.org/dnkl/foot/issues/1582 + + ### Changed ### Deprecated ### Removed diff --git a/config.c b/config.c index d2b75180..6a8bb0a8 100644 --- a/config.c +++ b/config.c @@ -1383,6 +1383,16 @@ parse_section_cursor(struct context *ctx) (int *)&conf->cursor.style); } + else if (streq(key, "unfocused-style")) { + _Static_assert(sizeof(conf->cursor.unfocused_style) == sizeof(int), + "enum is not 32-bit"); + + return value_to_enum( + ctx, + (const char *[]){"unchanged", "hollow", "none", NULL}, + (int *)&conf->cursor.unfocused_style); + } + else if (streq(key, "blink")) return value_to_bool(ctx, &conf->cursor.blink); @@ -3090,6 +3100,7 @@ config_load(struct config *conf, const char *conf_path, .cursor = { .style = CURSOR_BLOCK, + .unfocused_style = CURSOR_UNFOCUSED_HOLLOW, .blink = false, .color = { .text = 0, diff --git a/config.h b/config.h index 30219ff0..df3d45f9 100644 --- a/config.h +++ b/config.h @@ -28,6 +28,11 @@ struct font_size_adjustment { }; enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM }; +enum cursor_unfocused_style { + CURSOR_UNFOCUSED_UNCHANGED, + CURSOR_UNFOCUSED_HOLLOW, + CURSOR_UNFOCUSED_NONE +}; enum conf_size_type {CONF_SIZE_PX, CONF_SIZE_CELLS}; @@ -256,6 +261,7 @@ struct config { struct { enum cursor_style style; + enum cursor_unfocused_style unfocused_style; bool blink; struct { uint32_t text; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 2c50ca24..8cd0560f 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -500,6 +500,15 @@ applications can change these at runtime. *beam* or *underline*. Note that this can be overridden by applications. Default: _block_. +*unfocused-style* + Configures how the cursor is rendered when the terminal window is + unfocused. Possible values are: + + - unchanged: render cursor in exactly the same way as when the + window has focus. + - hollow: render a block cursor, but hollowed out. + - none: do not display any cursor at all. + *blink* Boolean. Enables blinking cursor. Note that this can be overridden by applications. Default: _no_. diff --git a/render.c b/render.c index bda43f1a..804ccdc3 100644 --- a/render.c +++ b/render.c @@ -305,8 +305,8 @@ color_brighten(const struct terminal *term, uint32_t color) } static void -draw_unfocused_block(const struct terminal *term, pixman_image_t *pix, - const pixman_color_t *color, int x, int y, int cell_cols) +draw_hollow_block(const struct terminal *term, pixman_image_t *pix, + const pixman_color_t *color, int x, int y, int cell_cols) { const int scale = (int)roundf(term->scale); const int width = min(min(scale, term->cell_width), term->cell_height); @@ -429,10 +429,23 @@ draw_cursor(const struct terminal *term, const struct cell *cell, switch (term->cursor_style) { case CURSOR_BLOCK: - if (unlikely(!term->kbd_focus)) - draw_unfocused_block(term, pix, &cursor_color, x, y, cols); + if (unlikely(!term->kbd_focus)) { + switch (term->conf->cursor.unfocused_style) { + case CURSOR_UNFOCUSED_UNCHANGED: + break; - else if (likely(term->cursor_blink.state == CURSOR_BLINK_ON)) { + case CURSOR_UNFOCUSED_HOLLOW: + draw_hollow_block(term, pix, fg, x, y, cols); + return; + + case CURSOR_UNFOCUSED_NONE: + return; + } + } + + if (likely(term->cursor_blink.state == CURSOR_BLINK_ON) || + !term->kbd_focus) + { *fg = text_color; pixman_image_fill_rectangles( PIXMAN_OP_SRC, pix, &cursor_color, 1, @@ -1513,7 +1526,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat, /* Hollow cursor */ if (start >= 0 && end <= term->cols) { int cols = end - start; - draw_unfocused_block(term, buf->pix[0], &cursor_color, x, y, cols); + draw_hollow_block(term, buf->pix[0], &cursor_color, x, y, cols); } term_ime_set_cursor_rect( @@ -3373,7 +3386,7 @@ render_search_box(struct terminal *term) /* TODO: how do we handle a partially hidden rectangle? */ if (start >= 0 && end <= visible_cells) { - draw_unfocused_block( + draw_hollow_block( term, buf->pix[0], &fg, x + start * term->cell_width, y, end - start); } term_ime_set_cursor_rect(term, diff --git a/tests/test-config.c b/tests/test-config.c index b54dd23e..3d4d345c 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -635,6 +635,12 @@ test_section_cursor(void) (const char *[]){"block", "beam", "underline"}, (int []){CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE}, (int *)&conf.cursor.style); + test_enum( + &ctx, &parse_section_cursor, "unfocused-style", + 3, + (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_pt_or_px(&ctx, &parse_section_cursor, "beam-thickness", &conf.cursor.beam_thickness);