Add a cursor-style option, from Alexis Hildebrandt in GitHub issue 2960.
authornicm <nicm@openbsd.org>
Wed, 3 Nov 2021 13:37:17 +0000 (13:37 +0000)
committernicm <nicm@openbsd.org>
Wed, 3 Nov 2021 13:37:17 +0000 (13:37 +0000)
usr.bin/tmux/input.c
usr.bin/tmux/options-table.c
usr.bin/tmux/options.c
usr.bin/tmux/screen.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h
usr.bin/tmux/tty.c

index 90f0bf7..b057e51 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: input.c,v 1.194 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: input.c,v 1.195 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1619,7 +1619,7 @@ input_csi_dispatch(struct input_ctx *ictx)
        case INPUT_CSI_DECSCUSR:
                n = input_get(ictx, 0, 0, 0);
                if (n != -1)
-                       screen_set_cursor_style(s, n);
+                       screen_set_cursor_style(n, &s->cstyle, &s->mode);
                break;
        case INPUT_CSI_XDA:
                n = input_get(ictx, 0, 0, 0);
@@ -1685,6 +1685,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
                        break;
                case 12:
                        screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING);
+                       screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
                        break;
                case 25:        /* TCEM */
                        screen_write_mode_clear(sctx, MODE_CURSOR);
@@ -1774,6 +1775,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
                        break;
                case 12:
                        screen_write_mode_set(sctx, MODE_CURSOR_BLINKING);
+                       screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
                        break;
                case 25:        /* TCEM */
                        screen_write_mode_set(sctx, MODE_CURSOR);
index d0511e2..9724fab 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: options-table.c,v 1.153 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: options-table.c,v 1.154 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -57,6 +57,10 @@ static const char *options_table_bell_action_list[] = {
 static const char *options_table_visual_bell_list[] = {
        "off", "on", "both", NULL
 };
+static const char *options_table_cursor_style_list[] = {
+       "default", "blinking-block", "block", "blinking-underline", "underline",
+       "blinking-bar", "bar", NULL
+};
 static const char *options_table_pane_status_list[] = {
        "off", "top", "bottom", NULL
 };
@@ -243,6 +247,14 @@ const struct options_table_entry options_table[] = {
          .text = "Colour of the cursor."
        },
 
+       { .name = "cursor-style",
+         .type = OPTIONS_TABLE_CHOICE,
+         .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
+         .choices = options_table_cursor_style_list,
+         .default_num = 0,
+         .text = "Style of the cursor."
+       },
+
        { .name = "default-terminal",
          .type = OPTIONS_TABLE_STRING,
          .scope = OPTIONS_TABLE_SERVER,
index a4af7cd..7fcf6c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.66 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: options.c,v 1.67 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1122,6 +1122,14 @@ options_push_changes(const char *name)
                        wp->screen->default_ccolour = c;
                }
        }
+       if (strcmp(name, "cursor-style") == 0) {
+               RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
+                       wp->screen->default_mode = 0;
+                       screen_set_cursor_style(options_get_number(wp->options,
+                           name), &wp->screen->default_cstyle,
+                           &wp->screen->default_mode);
+               }
+       }
        if (strcmp(name, "key-table") == 0) {
                TAILQ_FOREACH(loop, &clients, entry)
                        server_client_set_key_table(loop, NULL);
index 0ac7f62..ecf9cf5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: screen.c,v 1.77 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: screen.c,v 1.78 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -82,6 +82,8 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
        s->path = NULL;
 
        s->cstyle = SCREEN_CURSOR_DEFAULT;
+       s->default_cstyle = SCREEN_CURSOR_DEFAULT;
+       s->default_mode = 0;
        s->ccolour = -1;
        s->default_ccolour = -1;
        s->tabs = NULL;
@@ -152,38 +154,38 @@ screen_reset_tabs(struct screen *s)
                bit_set(s->tabs, i);
 }
 
-/* Set screen cursor style. */
+/* Set screen cursor style and mode. */
 void
-screen_set_cursor_style(struct screen *s, u_int style)
+screen_set_cursor_style(u_int style, enum screen_cursor_style *cstyle,
+    int *mode)
 {
-       log_debug("%s: new %u, was %u", __func__, style, s->cstyle);
        switch (style) {
        case 0:
-               s->cstyle = SCREEN_CURSOR_DEFAULT;
+               *cstyle = SCREEN_CURSOR_DEFAULT;
                break;
        case 1:
-               s->cstyle = SCREEN_CURSOR_BLOCK;
-               s->mode |= MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_BLOCK;
+               *mode |= MODE_CURSOR_BLINKING;
                break;
        case 2:
-               s->cstyle = SCREEN_CURSOR_BLOCK;
-               s->mode &= ~MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_BLOCK;
+               *mode &= ~MODE_CURSOR_BLINKING;
                break;
        case 3:
-               s->cstyle = SCREEN_CURSOR_UNDERLINE;
-               s->mode |= MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_UNDERLINE;
+               *mode |= MODE_CURSOR_BLINKING;
                break;
        case 4:
-               s->cstyle = SCREEN_CURSOR_UNDERLINE;
-               s->mode &= ~MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_UNDERLINE;
+               *mode &= ~MODE_CURSOR_BLINKING;
                break;
        case 5:
-               s->cstyle = SCREEN_CURSOR_BAR;
-               s->mode |= MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_BAR;
+               *mode |= MODE_CURSOR_BLINKING;
                break;
        case 6:
-               s->cstyle = SCREEN_CURSOR_BAR;
-               s->mode &= ~MODE_CURSOR_BLINKING;
+               *cstyle = SCREEN_CURSOR_BAR;
+               *mode &= ~MODE_CURSOR_BLINKING;
                break;
        }
 }
index 141461d..d6d3d1a 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.868 2021/11/01 09:34:49 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.869 2021/11/03 13:37:17 nicm Exp $
 .\"
 .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
 .\"
@@ -14,7 +14,7 @@
 .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: November 1 2021 $
+.Dd $Mdocdate: November 3 2021 $
 .Dt TMUX 1
 .Os
 .Sh NAME
@@ -4426,6 +4426,16 @@ Each entry in the array defines the colour
 uses when the colour with that index is requested.
 The index may be from zero to 255.
 .Pp
+.It Ic cursor-style Ar style
+Set the style of the cursor. Available styles are:
+.Ic default ,
+.Ic blinking-block ,
+.Ic block ,
+.Ic blinking-underline ,
+.Ic underline ,
+.Ic blinking-bar ,
+.Ic bar .
+.Pp
 .It Xo Ic remain-on-exit
 .Op Ic on | off | failed
 .Xc
index 0c7ddd2..36935c8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1153 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1154 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -530,6 +530,7 @@ enum tty_code_code {
 #define MODE_CRLF 0x4000
 #define MODE_KEXTENDED 0x8000
 #define MODE_CURSOR_VERY_VISIBLE 0x10000
+#define MODE_CURSOR_BLINKING_SET 0x20000
 
 #define ALL_MODES 0xffffff
 #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
@@ -779,6 +780,7 @@ struct screen {
        u_int                            cy;      /* cursor y */
 
        enum screen_cursor_style         cstyle;  /* cursor style */
+       enum screen_cursor_style         default_cstyle;
        int                              ccolour; /* cursor colour */
        int                              default_ccolour;
 
@@ -786,6 +788,7 @@ struct screen {
        u_int                            rlower;  /* scroll region bottom */
 
        int                              mode;
+       int                              default_mode;
 
        u_int                            saved_cx;
        u_int                            saved_cy;
@@ -2793,7 +2796,7 @@ void       screen_init(struct screen *, u_int, u_int, u_int);
 void    screen_reinit(struct screen *);
 void    screen_free(struct screen *);
 void    screen_reset_tabs(struct screen *);
-void    screen_set_cursor_style(struct screen *, u_int);
+void    screen_set_cursor_style(u_int, enum screen_cursor_style *, int *);
 void    screen_set_cursor_colour(struct screen *, int);
 int     screen_set_title(struct screen *, const char *);
 void    screen_set_path(struct screen *, const char *);
index 12c0ff3..4e13938 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.410 2021/11/01 09:34:49 nicm Exp $ */
+/* $OpenBSD: tty.c,v 1.411 2021/11/03 13:37:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -668,11 +668,11 @@ tty_force_cursor_colour(struct tty *tty, int c)
        tty->ccolour = c;
 }
 
-static void
-tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s)
+static int
+tty_update_cursor(struct tty *tty, int mode, struct screen *s)
 {
        enum screen_cursor_style        cstyle;
-       int                             ccolour;
+       int                             ccolour, changed, cmode = mode;
 
        /* Set cursor colour if changed. */
        if (s != NULL) {
@@ -683,19 +683,32 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s)
        }
 
        /* If cursor is off, set as invisible. */
-       if (~mode & MODE_CURSOR) {
-               if (changed & MODE_CURSOR)
+       if (~cmode & MODE_CURSOR) {
+               if (tty->mode & MODE_CURSOR)
                        tty_putcode(tty, TTYC_CIVIS);
-               return;
+               return (cmode);
        }
 
        /* Check if blinking or very visible flag changed or style changed. */
        if (s == NULL)
                cstyle = tty->cstyle;
-       else
+       else {
                cstyle = s->cstyle;
+               if (cstyle == SCREEN_CURSOR_DEFAULT) {
+                       if (~cmode & MODE_CURSOR_BLINKING_SET) {
+                               if (s->default_mode & MODE_CURSOR_BLINKING)
+                                       cmode |= MODE_CURSOR_BLINKING;
+                               else
+                                       cmode &= ~MODE_CURSOR_BLINKING;
+                       }
+                       cstyle = s->default_cstyle;
+               }
+       }
+
+       /* If nothing changed, do nothing. */
+       changed = cmode ^ tty->mode;
        if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle)
-               return;
+               return (cmode);
 
        /*
         * Set cursor style. If an explicit style has been set with DECSCUSR,
@@ -713,49 +726,56 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s)
                        else
                                tty_putcode1(tty, TTYC_SS, 0);
                }
-               if (mode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE))
+               if (cmode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE))
                        tty_putcode(tty, TTYC_CVVIS);
                break;
        case SCREEN_CURSOR_BLOCK:
                if (tty_term_has(tty->term, TTYC_SS)) {
-                       if (mode & MODE_CURSOR_BLINKING)
+                       if (cmode & MODE_CURSOR_BLINKING)
                                tty_putcode1(tty, TTYC_SS, 1);
                        else
                                tty_putcode1(tty, TTYC_SS, 2);
-               } else if (mode & MODE_CURSOR_BLINKING)
+               } else if (cmode & MODE_CURSOR_BLINKING)
                        tty_putcode(tty, TTYC_CVVIS);
                break;
        case SCREEN_CURSOR_UNDERLINE:
                if (tty_term_has(tty->term, TTYC_SS)) {
-                       if (mode & MODE_CURSOR_BLINKING)
+                       if (cmode & MODE_CURSOR_BLINKING)
                                tty_putcode1(tty, TTYC_SS, 3);
                        else
                                tty_putcode1(tty, TTYC_SS, 4);
-               } else if (mode & MODE_CURSOR_BLINKING)
+               } else if (cmode & MODE_CURSOR_BLINKING)
                        tty_putcode(tty, TTYC_CVVIS);
                break;
        case SCREEN_CURSOR_BAR:
                if (tty_term_has(tty->term, TTYC_SS)) {
-                       if (mode & MODE_CURSOR_BLINKING)
+                       if (cmode & MODE_CURSOR_BLINKING)
                                tty_putcode1(tty, TTYC_SS, 5);
                        else
                                tty_putcode1(tty, TTYC_SS, 6);
-               } else if (mode & MODE_CURSOR_BLINKING)
+               } else if (cmode & MODE_CURSOR_BLINKING)
                        tty_putcode(tty, TTYC_CVVIS);
                break;
        }
        tty->cstyle = cstyle;
+       return (cmode);
  }
 
 void
 tty_update_mode(struct tty *tty, int mode, struct screen *s)
 {
+       struct tty_term *term = tty->term;
        struct client   *c = tty->client;
        int              changed;
 
        if (tty->flags & TTY_NOCURSOR)
                mode &= ~MODE_CURSOR;
 
+       if (tty_update_cursor(tty, mode, s) & MODE_CURSOR_BLINKING)
+               mode |= MODE_CURSOR_BLINKING;
+       else
+               mode &= ~MODE_CURSOR_BLINKING;
+
        changed = mode ^ tty->mode;
        if (log_get_level() != 0 && changed != 0) {
                log_debug("%s: current mode %s", c->name,
@@ -764,9 +784,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
                    screen_mode_to_string(mode));
        }
 
-       tty_update_cursor(tty, mode, changed, s);
-       if ((changed & ALL_MOUSE_MODES) &&
-           tty_term_has(tty->term, TTYC_KMOUS)) {
+       if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) {
                /*
                 * If the mouse modes have changed, clear any that are set and
                 * apply again. There are differences in how terminals track