From ab102f188e86bdbfce1d4de2ef633092a906e8fe Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 6 Nov 2023 15:46:44 -0600 Subject: refactor: move background color detection into Lua --- src/nvim/api/ui.c | 9 ---- src/nvim/option.c | 17 -------- src/nvim/tui/input.c | 114 +-------------------------------------------------- src/nvim/tui/input.h | 1 - src/nvim/tui/tui.c | 9 +--- 5 files changed, 3 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 3d013435f7..a215317a83 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -348,15 +348,6 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; } - if (strequal(name.data, "term_background")) { - VALIDATE_T("term_background", kObjectTypeString, value.type, { - return; - }); - set_tty_background(value.data.string.data); - ui->term_background = string_to_cstr(value.data.string); - return; - } - if (strequal(name.data, "stdin_fd")) { VALIDATE_T("stdin_fd", kObjectTypeInteger, value.type, { return; diff --git a/src/nvim/option.c b/src/nvim/option.c index 23d5960579..d3a8e2ce73 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3183,23 +3183,6 @@ bool set_tty_option(const char *name, char *value) return false; } -void set_tty_background(const char *value) -{ - if (option_was_set("bg") || strequal(p_bg, value)) { - // background is already set... ignore - return; - } - if (starting) { - // Wait until after startup, so OptionSet is triggered. - do_cmdline_cmd((value[0] == 'l') - ? "autocmd VimEnter * ++once ++nested :lua if not vim.api.nvim_get_option_info2('bg', {}).was_set then vim.o.bg = 'light' end" - : "autocmd VimEnter * ++once ++nested :lua if not vim.api.nvim_get_option_info2('bg', {}).was_set then vim.o.bg = 'dark' end"); - } else { - set_option_value_give_err("bg", CSTR_AS_OPTVAL((char *)value), 0); - reset_option_was_set("bg"); - } -} - /// Find index for an option /// /// @param[in] arg Option name. diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 36d6566c7d..7dce8473d5 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -124,7 +124,6 @@ void tinput_init(TermInput *input, Loop *loop) input->loop = loop; input->paste = 0; input->in_fd = STDIN_FILENO; - input->waiting_for_bg_response = 0; input->extkeys_type = kExtkeysNone; input->ttimeout = (bool)p_ttimeout; input->ttimeoutlen = p_ttm; @@ -579,113 +578,6 @@ static HandleState handle_bracketed_paste(TermInput *input) return kNotApplicable; } -static void set_bg(char *bgvalue) -{ - if (ui_client_attached) { - MAXSIZE_TEMP_ARRAY(args, 2); - ADD_C(args, CSTR_AS_OBJ("term_background")); - ADD_C(args, CSTR_AS_OBJ(bgvalue)); - rpc_send_event(ui_client_channel_id, "nvim_ui_set_option", args); - } -} - -// During startup, tui.c requests the background color (see `ext.get_bg`). -// -// Here in input.c, we watch for the terminal response `\e]11;COLOR\a`. If -// COLOR matches `rgb:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, -// then compute the luminance[1] of the RGB color and classify it as light/dark -// accordingly. Note that the color components may have anywhere from one to -// four hex digits, and require scaling accordingly as values out of 4, 8, 12, -// or 16 bits. Also note the A(lpha) component is optional, and is parsed but -// ignored in the calculations. -// -// [1] https://en.wikipedia.org/wiki/Luma_%28video%29 -HandleState handle_background_color(TermInput *input) -{ - if (input->waiting_for_bg_response <= 0) { - return kNotApplicable; - } - size_t count = 0; - size_t component = 0; - size_t header_size = 0; - size_t num_components = 0; - size_t buf_size = rbuffer_size(input->read_stream.buffer); - uint16_t rgb[] = { 0, 0, 0 }; - uint16_t rgb_max[] = { 0, 0, 0 }; - bool eat_backslash = false; - bool done = false; - bool bad = false; - if (buf_size >= 9 - && !rbuffer_cmp(input->read_stream.buffer, "\x1b]11;rgb:", 9)) { - header_size = 9; - num_components = 3; - } else if (buf_size >= 10 - && !rbuffer_cmp(input->read_stream.buffer, "\x1b]11;rgba:", 10)) { - header_size = 10; - num_components = 4; - } else if (buf_size < 10 - && !rbuffer_cmp(input->read_stream.buffer, - "\x1b]11;rgba", buf_size)) { - // An incomplete sequence was found, waiting for the next input. - return kIncomplete; - } else { - input->waiting_for_bg_response--; - if (input->waiting_for_bg_response == 0) { - DLOG("did not get a response for terminal background query"); - } - return kNotApplicable; - } - RBUFFER_EACH(input->read_stream.buffer, c, i) { - count = i + 1; - // Skip the header. - if (i < header_size) { - continue; - } - if (eat_backslash) { - done = true; - break; - } else if (c == '\x07') { - done = true; - break; - } else if (c == '\x1b') { - eat_backslash = true; - } else if (bad) { - // ignore - } else if ((c == '/') && (++component < num_components)) { - // work done in condition - } else if (ascii_isxdigit(c)) { - if (component < 3 && rgb_max[component] != 0xffff) { - rgb_max[component] = (uint16_t)((rgb_max[component] << 4) | 0xf); - rgb[component] = (uint16_t)((rgb[component] << 4) | hex2nr(c)); - } - } else { - bad = true; - } - } - if (done && !bad && rgb_max[0] && rgb_max[1] && rgb_max[2]) { - rbuffer_consumed(input->read_stream.buffer, count); - double r = (double)rgb[0] / (double)rgb_max[0]; - double g = (double)rgb[1] / (double)rgb_max[1]; - double b = (double)rgb[2] / (double)rgb_max[2]; - double luminance = (0.299 * r) + (0.587 * g) + (0.114 * b); // CCIR 601 - bool is_dark = luminance < 0.5; - char *bgvalue = is_dark ? "dark" : "light"; - DLOG("bg response: %s", bgvalue); - ui_client_bg_response = is_dark ? kTrue : kFalse; - set_bg(bgvalue); - input->waiting_for_bg_response = 0; - } else if (!done && !bad) { - // An incomplete sequence was found, waiting for the next input. - return kIncomplete; - } else { - input->waiting_for_bg_response = 0; - rbuffer_consumed(input->read_stream.buffer, count); - DLOG("failed to parse bg response"); - return kNotApplicable; - } - return kComplete; -} - static void handle_osc_event(TermInput *input, const TermKeyKey *key) { assert(input); @@ -712,14 +604,12 @@ static void handle_osc_event(TermInput *input, const TermKeyKey *key) static void handle_raw_buffer(TermInput *input, bool force) { HandleState is_paste = kNotApplicable; - HandleState is_bc = kNotApplicable; do { if (!force && (handle_focus_event(input) - || (is_paste = handle_bracketed_paste(input)) != kNotApplicable - || (is_bc = handle_background_color(input)) != kNotApplicable)) { - if (is_paste == kIncomplete || is_bc == kIncomplete) { + || (is_paste = handle_bracketed_paste(input)) != kNotApplicable)) { + if (is_paste == kIncomplete) { // Wait for the next input, leaving it in the raw buffer due to an // incomplete sequence. return; diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index 8b4d1ba74b..01514269be 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -24,7 +24,6 @@ typedef struct term_input { // Phases: -1=all 0=disabled 1=first-chunk 2=continue 3=last-chunk int8_t paste; bool ttimeout; - int8_t waiting_for_bg_response; int8_t waiting_for_csiu_response; ExtkeysType extkeys_type; OptInt ttimeoutlen; diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 177ef0c3cf..8aab4d836c 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -133,7 +133,6 @@ struct TUIData { int reset_scroll_region; int set_cursor_style, reset_cursor_style; int save_title, restore_title; - int get_bg; int set_underline_style; int set_underline_color; int enable_extended_keys, disable_extended_keys; @@ -250,7 +249,6 @@ static void terminfo_start(TUIData *tui) tui->unibi_ext.reset_scroll_region = -1; tui->unibi_ext.set_cursor_style = -1; tui->unibi_ext.reset_cursor_style = -1; - tui->unibi_ext.get_bg = -1; tui->unibi_ext.set_underline_color = -1; tui->unibi_ext.enable_extended_keys = -1; tui->unibi_ext.disable_extended_keys = -1; @@ -327,9 +325,7 @@ static void terminfo_start(TUIData *tui) unibi_out(tui, unibi_enter_ca_mode); unibi_out(tui, unibi_keypad_xmit); unibi_out(tui, unibi_clear_screen); - // Ask the terminal to send us the background color. - tui->input.waiting_for_bg_response = 5; - unibi_out_ext(tui, tui->unibi_ext.get_bg); + // Enable bracketed paste unibi_out_ext(tui, tui->unibi_ext.enable_bracketed_paste); @@ -1882,9 +1878,6 @@ static void patch_terminfo_bugs(TUIData *tui, const char *term, const char *colo #define XTERM_SETAB_16 \ "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e39%;m" - tui->unibi_ext.get_bg = (int)unibi_add_ext_str(ut, "ext.get_bg", - "\x1b]11;?\x07"); - // Query the terminal to see if it supports CSI u key encoding by writing CSI // ? u followed by a request for the primary device attributes (CSI c) // See https://sw.kovidgoyal.net/kitty/keyboard-protocol/#detection-of-support-for-this-protocol -- cgit From 8d9789a0f3b748b75ac4ae1b8e43d27af40d49fe Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Tue, 7 Nov 2023 11:31:21 -0600 Subject: docs: deprecate the "term_background" UI field --- src/nvim/api/ui.c | 1 - src/nvim/ui.c | 5 ++++- src/nvim/ui.h | 3 ++- src/nvim/ui_client.c | 5 +---- src/nvim/ui_client.h | 4 ---- 5 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index a215317a83..e6d9035b0d 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -120,7 +120,6 @@ void remote_ui_disconnect(uint64_t channel_id) // Destroy `ui`. XFREE_CLEAR(ui->term_name); - XFREE_CLEAR(ui->term_background); xfree(ui); } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index dc38c061b0..3e5bfba315 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -623,7 +623,10 @@ Array ui_array(void) // TUI fields. (`stdin_fd` is intentionally omitted.) PUT(info, "term_name", CSTR_TO_OBJ(ui->term_name)); - PUT(info, "term_background", CSTR_TO_OBJ(ui->term_background)); + + // term_background is deprecated. Populate with an empty string + PUT(info, "term_background", CSTR_TO_OBJ("")); + PUT(info, "term_colors", INTEGER_OBJ(ui->term_colors)); PUT(info, "stdin_tty", BOOLEAN_OBJ(ui->stdin_tty)); PUT(info, "stdout_tty", BOOLEAN_OBJ(ui->stdout_tty)); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index d399802c99..3feb0bf603 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -104,7 +104,8 @@ struct ui_t { // TUI fields. char *term_name; - char *term_background; + char *term_background; ///< Deprecated. No longer needed since background color detection happens + ///< in Lua. To be removed in a future release. int term_colors; bool stdin_tty; bool stdout_tty; diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index dac690822b..2f91257a5d 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -84,10 +84,7 @@ void ui_client_attach(int width, int height, char *term) if (term) { PUT_C(opts, "term_name", CSTR_AS_OBJ(term)); } - if (ui_client_bg_response != kNone) { - bool is_dark = (ui_client_bg_response == kTrue); - PUT_C(opts, "term_background", CSTR_AS_OBJ(is_dark ? "dark" : "light")); - } + PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors)); if (!ui_client_is_remote) { PUT_C(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h index fbee942cdf..db1ab463f8 100644 --- a/src/nvim/ui_client.h +++ b/src/nvim/ui_client.h @@ -31,10 +31,6 @@ EXTERN int ui_client_exit_status INIT( = 0); /// Whether ui client has sent nvim_ui_attach yet EXTERN bool ui_client_attached INIT( = false); -/// Whether ui client has gotten a response about the bg color of the terminal, -/// kTrue=dark, kFalse=light, kNone=no response yet -EXTERN TriState ui_client_bg_response INIT( = kNone); - /// The ui client should forward its stdin to the nvim process /// by convention, this uses fd=3 (next free number after stdio) EXTERN bool ui_client_forward_stdin INIT( = false); -- cgit From 22eb2ba18336df6cd70a88f666818ee5d8ba92d2 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 13 Nov 2023 13:39:04 -0600 Subject: fix(lua): do not schedule events if Nvim is exiting If Nvim is in the process of exiting then we do not want to allocate any new refs onto the event loop, because they will not be freed and will result in a memory leak. --- src/nvim/lua/executor.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 716fe5e481..aed96a539a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -366,6 +366,12 @@ static void nlua_schedule_event(void **argv) static int nlua_schedule(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { + // If Nvim is exiting don't schedule tasks to run in the future. Any refs + // allocated here will not be cleaned up otherwise + if (exiting) { + return 0; + } + if (lua_type(lstate, 1) != LUA_TFUNCTION) { lua_pushliteral(lstate, "vim.schedule: expected function"); return lua_error(lstate); -- cgit