aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerw7 <erw7.github@gmail.com>2020-03-20 03:31:10 +0900
committererw7 <erw7.github@gmail.com>2020-03-21 18:06:59 +0900
commit9333f86ab7d0e85d9f658bfe455860771de9b997 (patch)
tree3ec96439c76f26f48623757030095d27e95be13b
parent87d892afa0475644e91d9c8a57b7c35491c4dc32 (diff)
downloadrneovim-9333f86ab7d0e85d9f658bfe455860771de9b997.tar.gz
rneovim-9333f86ab7d0e85d9f658bfe455860771de9b997.tar.bz2
rneovim-9333f86ab7d0e85d9f658bfe455860771de9b997.zip
TUI: do not use "nvim_get_option" in tui thread
Since "nvim_get_option" is executed on the tui thread as a C function instead of msgpack-rpc, it accesses global variables that may change on the main thread.
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/tui/input.c26
-rw-r--r--src/nvim/tui/input.h2
-rw-r--r--src/nvim/tui/tui.c6
-rw-r--r--test/functional/ui/options_spec.lua14
5 files changed, 31 insertions, 19 deletions
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 02102fc168..e7c1a3fe88 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2587,6 +2587,7 @@ return {
type='bool', scope={'global'},
vi_def=true,
vim=true,
+ redraw={'ui_option'},
varname='p_ttimeout',
defaults={if_true={vi=true}}
},
@@ -2594,6 +2595,7 @@ return {
full_name='ttimeoutlen', abbreviation='ttm',
type='number', scope={'global'},
vi_def=true,
+ redraw={'ui_option'},
varname='p_ttm',
defaults={if_true={vi=50}}
},
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 951cb50c3c..bbee7e4712 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -31,6 +31,10 @@ void tinput_init(TermInput *input, Loop *loop)
input->paste = 0;
input->in_fd = STDIN_FILENO;
input->waiting_for_bg_response = 0;
+ // The main thread is waiting for the UI thread to call CONTINUE, so it can
+ // safely access global variables.
+ input->ttimeout = (bool)p_ttimeout;
+ input->ttimeoutlen = p_ttm;
input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE);
uv_mutex_init(&input->key_buffer_mutex);
uv_cond_init(&input->key_buffer_cond);
@@ -285,21 +289,6 @@ static TermKeyResult tk_getkey(TermKey *tk, TermKeyKey *key, bool force)
static void tinput_timer_cb(TimeWatcher *watcher, void *data);
-static int get_key_code_timeout(void)
-{
- Integer ms = -1;
- // Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'.
- Error err = ERROR_INIT;
- if (nvim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) {
- Object rv = nvim_get_option(cstr_as_string("ttimeoutlen"), &err);
- if (!ERROR_SET(&err)) {
- ms = rv.data.integer;
- }
- }
- api_clear_error(&err);
- return (int)ms;
-}
-
static void tk_getkeys(TermInput *input, bool force)
{
TermKeyKey key;
@@ -324,12 +313,11 @@ static void tk_getkeys(TermInput *input, bool force)
// yet contain all the bytes required. `key` structure indicates what
// termkey_getkey_force() would return.
- int ms = get_key_code_timeout();
-
- if (ms > 0) {
+ if (input->ttimeout && input->ttimeoutlen >= 0) {
// Stop the current timer if already running
time_watcher_stop(&input->timer_handle);
- time_watcher_start(&input->timer_handle, tinput_timer_cb, (uint32_t)ms, 0);
+ time_watcher_start(&input->timer_handle, tinput_timer_cb,
+ (uint64_t)input->ttimeoutlen, 0);
} else {
tk_getkeys(input, true);
}
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 77bd6fa132..b30546c815 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -12,7 +12,9 @@ typedef struct term_input {
// Phases: -1=all 0=disabled 1=first-chunk 2=continue 3=last-chunk
int8_t paste;
bool waiting;
+ bool ttimeout;
int8_t waiting_for_bg_response;
+ long ttimeoutlen;
TermKey *tk;
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 22f4501be2..99abdd033b 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -1292,6 +1292,12 @@ static void tui_option_set(UI *ui, String name, Object value)
data->print_attr_id = -1;
invalidate(ui, 0, data->grid.height, 0, data->grid.width);
}
+ if (strequal(name.data, "ttimeout")) {
+ data->input.ttimeout = value.data.boolean;
+ }
+ if (strequal(name.data, "ttimeoutlen")) {
+ data->input.ttimeoutlen = (long)value.data.integer;
+ }
}
static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index 581e196bbb..9646c3fdad 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -20,6 +20,8 @@ describe('UI receives option updates', function()
pumblend=0,
showtabline=1,
termguicolors=false,
+ ttimeout=true,
+ ttimeoutlen=50,
ext_cmdline=false,
ext_popupmenu=false,
ext_tabline=false,
@@ -108,6 +110,18 @@ describe('UI receives option updates', function()
eq(expected, screen.options)
end)
+ command("set nottimeout")
+ expected.ttimeout = false
+ screen:expect(function()
+ eq(expected, screen.options)
+ end)
+
+ command("set ttimeoutlen=100")
+ expected.ttimeoutlen = 100
+ screen:expect(function()
+ eq(expected, screen.options)
+ end)
+
command("set all&")
screen:expect(function()
eq(defaults, screen.options)