From cd6b3da6653dfb92d51534d5ff83376e80e64381 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 7 Jul 2021 20:33:29 +0530 Subject: [PATCH] Fix turning off cursor blink via escape codes not working Also fix cursor blink stopping after terminal reset. The default cursor state should be blinking. Fixes #3808 ... --- docs/changelog.rst | 3 +++ kitty/child-monitor.c | 2 +- kitty/cursor.c | 14 +++++++++----- kitty/data-types.h | 2 +- kitty/screen.c | 12 ++++++------ 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 00a395f48..c557d3f75 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -19,6 +19,9 @@ To update |kitty|, :doc:`follow the instructions `. - diff kitten: Remove limit on max line length of 4096 characters (:iss:`3806`) +- Fix turning off cursor blink via escape codes not working (:iss:`3808`) + + 0.21.2 [2021-06-28] ---------------------- diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 70cd5b180..82a415586 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -523,7 +523,7 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow ans->is_visible = false; if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return; monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time; - bool cursor_blinking = OPT(cursor_blink_interval) > 0 && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after)); + bool cursor_blinking = OPT(cursor_blink_interval) > 0 && !cursor->non_blinking && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after)); bool do_draw_cursor = true; if (cursor_blinking) { int t = monotonic_t_to_ms(time_since_start_blink); diff --git a/kitty/cursor.c b/kitty/cursor.c index 4480a014a..69420b74a 100644 --- a/kitty/cursor.c +++ b/kitty/cursor.c @@ -24,7 +24,7 @@ dealloc(Cursor* self) { #define EQ(x) (a->x == b->x) static int __eq__(Cursor *a, Cursor *b) { - return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(dim) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink); + return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(dim) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(non_blinking); } static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" }; @@ -35,7 +35,7 @@ repr(Cursor *self) { return PyUnicode_FromFormat( "Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, dim=%R, decoration=%d, decoration_fg=#%08x)", self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES ? cursor_names[self->shape] : "INVALID"), - BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), BOOL(self->dim), self->decoration, self->decoration_fg + BOOL(!self->non_blinking), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), BOOL(self->dim), self->decoration, self->decoration_fg ); } @@ -232,12 +232,12 @@ reset_display_attrs(Cursor *self, PyObject *a UNUSED) { void cursor_reset(Cursor *self) { cursor_reset_display_attrs(self); self->x = 0; self->y = 0; - self->shape = NO_CURSOR_SHAPE; self->blink = false; + self->shape = NO_CURSOR_SHAPE; self->non_blinking = false; } void cursor_copy_to(Cursor *src, Cursor *dest) { #define CCY(x) dest->x = src->x; - CCY(x); CCY(y); CCY(shape); CCY(blink); + CCY(x); CCY(y); CCY(shape); CCY(non_blinking); CCY(bold); CCY(italic); CCY(strikethrough); CCY(dim); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg); } @@ -252,7 +252,11 @@ BOOL_GETSET(Cursor, italic) BOOL_GETSET(Cursor, reverse) BOOL_GETSET(Cursor, strikethrough) BOOL_GETSET(Cursor, dim) -BOOL_GETSET(Cursor, blink) + +static PyObject* blink_get(Cursor *self, void UNUSED *closure) { PyObject *ans = !self->non_blinking ? Py_True : Py_False; Py_INCREF(ans); return ans; } + +static int blink_set(Cursor *self, PyObject *value, void UNUSED *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); return -1; } self->non_blinking = PyObject_IsTrue(value) ? false : true; return 0; } + static PyMemberDef members[] = { {"x", T_UINT, offsetof(Cursor, x), 0, "x"}, diff --git a/kitty/data-types.h b/kitty/data-types.h index 54bc4f994..523ab80fc 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -224,7 +224,7 @@ typedef struct { typedef struct { PyObject_HEAD - bool bold, italic, reverse, strikethrough, blink, dim; + bool bold, italic, reverse, strikethrough, dim, non_blinking; unsigned int x, y; uint8_t decoration; CursorShape shape; diff --git a/kitty/screen.c b/kitty/screen.c index 1795ce6a9..66960c169 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -873,7 +873,7 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) { } break; case CONTROL_CURSOR_BLINK: - self->cursor->blink = val; + self->cursor->non_blinking = !val; break; case SAVE_CURSOR: screen_save_cursor(self); @@ -1679,8 +1679,8 @@ screen_set_cursor(Screen *self, unsigned int mode, uint8_t secondary) { blink = mode % 2; shape = (mode < 3) ? CURSOR_BLOCK : (mode < 5) ? CURSOR_UNDERLINE : (mode < 7) ? CURSOR_BEAM : NO_CURSOR_SHAPE; } - if (shape != self->cursor->shape || blink != self->cursor->blink) { - self->cursor->shape = shape; self->cursor->blink = blink; + if (shape != self->cursor->shape || blink != !self->cursor->non_blinking) { + self->cursor->shape = shape; self->cursor->non_blinking = !blink; } break; } @@ -1773,11 +1773,11 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) { case NUM_OF_CURSOR_SHAPES: shape = 1; break; case CURSOR_BLOCK: - shape = self->cursor->blink ? 0 : 2; break; + shape = self->cursor->non_blinking ? 2 : 0; break; case CURSOR_UNDERLINE: - shape = self->cursor->blink ? 3 : 4; break; + shape = self->cursor->non_blinking ? 4 : 3; break; case CURSOR_BEAM: - shape = self->cursor->blink ? 5 : 6; break; + shape = self->cursor->non_blinking ? 6 : 5; break; } shape = snprintf(buf, sizeof(buf), "1$r%d q", shape); } else if (strcmp("m", query) == 0) {