Change cursor style handling so tmux understands which sequences contain

blinking and sets the flag appropriately, means that it works whether
cnorm disables blinking or not. GitHub issue 2682.
This commit is contained in:
nicm 2021-06-10 07:36:47 +00:00
parent 84e22168a5
commit f9f97c8145
3 changed files with 120 additions and 43 deletions

View File

@ -81,7 +81,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
s->titles = NULL; s->titles = NULL;
s->path = NULL; s->path = NULL;
s->cstyle = 0; s->cstyle = SCREEN_CURSOR_DEFAULT;
s->ccolour = xstrdup(""); s->ccolour = xstrdup("");
s->tabs = NULL; s->tabs = NULL;
s->sel = NULL; s->sel = NULL;
@ -156,9 +156,35 @@ screen_reset_tabs(struct screen *s)
void void
screen_set_cursor_style(struct screen *s, u_int style) screen_set_cursor_style(struct screen *s, u_int style)
{ {
if (style <= 6) { switch (style)
s->cstyle = style; {
case 0:
s->cstyle = SCREEN_CURSOR_DEFAULT;
break;
case 1:
s->cstyle = SCREEN_CURSOR_BLOCK;
s->mode |= MODE_BLINKING;
break;
case 2:
s->cstyle = SCREEN_CURSOR_BLOCK;
s->mode &= ~MODE_BLINKING; s->mode &= ~MODE_BLINKING;
break;
case 3:
s->cstyle = SCREEN_CURSOR_UNDERLINE;
s->mode |= MODE_BLINKING;
break;
case 4:
s->cstyle = SCREEN_CURSOR_UNDERLINE;
s->mode &= ~MODE_BLINKING;
break;
case 5:
s->cstyle = SCREEN_CURSOR_BAR;
s->mode |= MODE_BLINKING;
break;
case 6:
s->cstyle = SCREEN_CURSOR_BAR;
s->mode &= ~MODE_BLINKING;
break;
} }
} }

14
tmux.h
View File

@ -794,6 +794,14 @@ struct style {
enum style_default_type default_type; enum style_default_type default_type;
}; };
/* Cursor style. */
enum screen_cursor_style {
SCREEN_CURSOR_DEFAULT,
SCREEN_CURSOR_BLOCK,
SCREEN_CURSOR_UNDERLINE,
SCREEN_CURSOR_BAR
};
/* Virtual screen. */ /* Virtual screen. */
struct screen_sel; struct screen_sel;
struct screen_titles; struct screen_titles;
@ -807,8 +815,8 @@ struct screen {
u_int cx; /* cursor x */ u_int cx; /* cursor x */
u_int cy; /* cursor y */ u_int cy; /* cursor y */
u_int cstyle; /* cursor style */ enum screen_cursor_style cstyle; /* cursor style */
char *ccolour; /* cursor colour string */ char *ccolour; /* cursor colour */
u_int rupper; /* scroll region top */ u_int rupper; /* scroll region top */
u_int rlower; /* scroll region bottom */ u_int rlower; /* scroll region bottom */
@ -1296,7 +1304,7 @@ struct tty {
u_int cx; u_int cx;
u_int cy; u_int cy;
u_int cstyle; enum screen_cursor_style cstyle;
char *ccolour; char *ccolour;
int oflag; int oflag;

117
tty.c
View File

@ -98,7 +98,7 @@ tty_init(struct tty *tty, struct client *c)
memset(tty, 0, sizeof *tty); memset(tty, 0, sizeof *tty);
tty->client = c; tty->client = c;
tty->cstyle = 0; tty->cstyle = SCREEN_CURSOR_DEFAULT;
tty->ccolour = xstrdup(""); tty->ccolour = xstrdup("");
if (tcgetattr(c->fd, &tty->tio) != 0) if (tcgetattr(c->fd, &tty->tio) != 0)
@ -392,10 +392,10 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
if (tty_term_has(tty->term, TTYC_SS) && tty->cstyle != 0) { if (tty->cstyle != SCREEN_CURSOR_DEFAULT) {
if (tty_term_has(tty->term, TTYC_SE)) if (tty_term_has(tty->term, TTYC_SE))
tty_raw(tty, tty_term_string(tty->term, TTYC_SE)); tty_raw(tty, tty_term_string(tty->term, TTYC_SE));
else else if (tty_term_has(tty->term, TTYC_SS))
tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0)); tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0));
} }
if (tty->mode & MODE_BRACKETPASTE) if (tty->mode & MODE_BRACKETPASTE)
@ -657,11 +657,9 @@ tty_force_cursor_colour(struct tty *tty, const char *ccolour)
void void
tty_update_mode(struct tty *tty, int mode, struct screen *s) tty_update_mode(struct tty *tty, int mode, struct screen *s)
{ {
struct client *c = tty->client; struct client *c = tty->client;
int changed; int changed;
enum screen_cursor_style cstyle = tty->cstyle;
if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0)
tty_force_cursor_colour(tty, s->ccolour);
if (tty->flags & TTY_NOCURSOR) if (tty->flags & TTY_NOCURSOR)
mode &= ~MODE_CURSOR; mode &= ~MODE_CURSOR;
@ -670,38 +668,83 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
if (changed != 0) if (changed != 0)
log_debug("%s: update mode %x to %x", c->name, tty->mode, mode); log_debug("%s: update mode %x to %x", c->name, tty->mode, mode);
/* if (s != NULL) {
* The cursor blinking flag can be reset by setting the cursor style, so if (strcmp(s->ccolour, tty->ccolour) != 0)
* set the style first. tty_force_cursor_colour(tty, s->ccolour);
*/ cstyle = s->cstyle;
if (s != NULL && tty->cstyle != s->cstyle) {
if (tty_term_has(tty->term, TTYC_SS)) {
if (s->cstyle == 0 && tty_term_has(tty->term, TTYC_SE))
tty_putcode(tty, TTYC_SE);
else
tty_putcode1(tty, TTYC_SS, s->cstyle);
}
tty->cstyle = s->cstyle;
changed |= (MODE_CURSOR|MODE_BLINKING);
} }
if (~mode & MODE_CURSOR) {
/* /* Cursor now off - set as invisible. */
* Cursor invisible (RM ?25) overrides cursor blinking (SM ?12 or RM if (changed & MODE_CURSOR)
* 34), and we need to be careful not send cnorm after cvvis since it
* can undo it.
*/
if (changed & (MODE_CURSOR|MODE_BLINKING)) {
log_debug("%s: cursor %s, %sblinking", __func__,
(mode & MODE_CURSOR) ? "on" : "off",
(mode & MODE_BLINKING) ? "" : "not ");
if (~mode & MODE_CURSOR)
tty_putcode(tty, TTYC_CIVIS); tty_putcode(tty, TTYC_CIVIS);
else if (mode & MODE_BLINKING) { } else if ((changed & (MODE_CURSOR|MODE_BLINKING)) ||
tty_putcode(tty, TTYC_CNORM); cstyle != tty->cstyle) {
if (tty_term_has(tty->term, TTYC_CVVIS)) /*
* Cursor now on, blinking flag changed or style changed. Start
* by setting the cursor to normal.
*/
tty_putcode(tty, TTYC_CNORM);
switch (cstyle) {
case SCREEN_CURSOR_DEFAULT:
/*
* If the old style wasn't default, then reset it to
* default.
*/
if (tty->cstyle != SCREEN_CURSOR_DEFAULT) {
if (tty_term_has(tty->term, TTYC_SE))
tty_putcode(tty, TTYC_SE);
else
tty_putcode1(tty, TTYC_SS, 0);
}
/* Set the cursor as very visible if necessary. */
if (mode & MODE_BLINKING)
tty_putcode(tty, TTYC_CVVIS); tty_putcode(tty, TTYC_CVVIS);
} else break;
tty_putcode(tty, TTYC_CNORM); case SCREEN_CURSOR_BLOCK:
/*
* Set style to either block blinking (1) or steady (2)
* if supported, otherwise just check the blinking
* flag.
*/
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_BLINKING)
tty_putcode1(tty, TTYC_SS, 1);
else
tty_putcode1(tty, TTYC_SS, 2);
} else if (mode & MODE_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
case SCREEN_CURSOR_UNDERLINE:
/*
* Set style to either underline blinking (3) or steady
* (4) if supported, otherwise just check the blinking
* flag.
*/
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_BLINKING)
tty_putcode1(tty, TTYC_SS, 3);
else
tty_putcode1(tty, TTYC_SS, 4);
} else if (mode & MODE_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
case SCREEN_CURSOR_BAR:
/*
* Set style to either bar blinking (5) or steady (6)
* if supported, otherwise just check the blinking
* flag.
*/
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_BLINKING)
tty_putcode1(tty, TTYC_SS, 5);
else
tty_putcode1(tty, TTYC_SS, 6);
} else if (mode & MODE_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
}
tty->cstyle = cstyle;
} }
if ((changed & ALL_MOUSE_MODES) && if ((changed & ALL_MOUSE_MODES) &&