config: add cursor.unfocused-style

This option controls how we render the cursor when the terminal window
is unfocused.

Possible values are:

* hollow: the default, and how we rendered the cursor before this
  patch.
* unchanged: render the cursor exactly the same way as when the window
  is focused.
* none: do not render any cursor at all

Closes #1582
This commit is contained in:
Daniel Eklöf 2024-04-09 16:28:54 +02:00
parent 9287946b36
commit e5a2ac4b57
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 59 additions and 7 deletions

View file

@ -52,6 +52,13 @@
## Unreleased ## Unreleased
### Added ### 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 ### Changed
### Deprecated ### Deprecated
### Removed ### Removed

View file

@ -1383,6 +1383,16 @@ parse_section_cursor(struct context *ctx)
(int *)&conf->cursor.style); (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")) else if (streq(key, "blink"))
return value_to_bool(ctx, &conf->cursor.blink); return value_to_bool(ctx, &conf->cursor.blink);
@ -3090,6 +3100,7 @@ config_load(struct config *conf, const char *conf_path,
.cursor = { .cursor = {
.style = CURSOR_BLOCK, .style = CURSOR_BLOCK,
.unfocused_style = CURSOR_UNFOCUSED_HOLLOW,
.blink = false, .blink = false,
.color = { .color = {
.text = 0, .text = 0,

View file

@ -28,6 +28,11 @@ struct font_size_adjustment {
}; };
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM }; 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}; enum conf_size_type {CONF_SIZE_PX, CONF_SIZE_CELLS};
@ -256,6 +261,7 @@ struct config {
struct { struct {
enum cursor_style style; enum cursor_style style;
enum cursor_unfocused_style unfocused_style;
bool blink; bool blink;
struct { struct {
uint32_t text; uint32_t text;

View file

@ -500,6 +500,15 @@ applications can change these at runtime.
*beam* or *underline*. Note that this can be overridden by *beam* or *underline*. Note that this can be overridden by
applications. Default: _block_. 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* *blink*
Boolean. Enables blinking cursor. Note that this can be overridden Boolean. Enables blinking cursor. Note that this can be overridden
by applications. Default: _no_. by applications. Default: _no_.

View file

@ -305,8 +305,8 @@ color_brighten(const struct terminal *term, uint32_t color)
} }
static void static void
draw_unfocused_block(const struct terminal *term, pixman_image_t *pix, draw_hollow_block(const struct terminal *term, pixman_image_t *pix,
const pixman_color_t *color, int x, int y, int cell_cols) const pixman_color_t *color, int x, int y, int cell_cols)
{ {
const int scale = (int)roundf(term->scale); const int scale = (int)roundf(term->scale);
const int width = min(min(scale, term->cell_width), term->cell_height); 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) { switch (term->cursor_style) {
case CURSOR_BLOCK: case CURSOR_BLOCK:
if (unlikely(!term->kbd_focus)) if (unlikely(!term->kbd_focus)) {
draw_unfocused_block(term, pix, &cursor_color, x, y, cols); 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; *fg = text_color;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(
PIXMAN_OP_SRC, pix, &cursor_color, 1, PIXMAN_OP_SRC, pix, &cursor_color, 1,
@ -1513,7 +1526,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat,
/* Hollow cursor */ /* Hollow cursor */
if (start >= 0 && end <= term->cols) { if (start >= 0 && end <= term->cols) {
int cols = end - start; 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( term_ime_set_cursor_rect(
@ -3373,7 +3386,7 @@ render_search_box(struct terminal *term)
/* TODO: how do we handle a partially hidden rectangle? */ /* TODO: how do we handle a partially hidden rectangle? */
if (start >= 0 && end <= visible_cells) { 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, buf->pix[0], &fg, x + start * term->cell_width, y, end - start);
} }
term_ime_set_cursor_rect(term, term_ime_set_cursor_rect(term,

View file

@ -635,6 +635,12 @@ test_section_cursor(void)
(const char *[]){"block", "beam", "underline"}, (const char *[]){"block", "beam", "underline"},
(int []){CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE}, (int []){CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE},
(int *)&conf.cursor.style); (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_boolean(&ctx, &parse_section_cursor, "blink", &conf.cursor.blink);
test_pt_or_px(&ctx, &parse_section_cursor, "beam-thickness", test_pt_or_px(&ctx, &parse_section_cursor, "beam-thickness",
&conf.cursor.beam_thickness); &conf.cursor.beam_thickness);