diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-09-18 11:37:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-18 11:37:22 +0200 |
commit | e63538f21c90112faafc65ae12766d1f9abd5bc0 (patch) | |
tree | f211af5f1926cb1fdde6083f2b51a52241c19967 /src | |
parent | 6d557e324fd4223fff3279a0112f40431c540163 (diff) | |
parent | 644a3f48b117abd1d0d0aab5ec96cd62392ca0f1 (diff) | |
download | rneovim-e63538f21c90112faafc65ae12766d1f9abd5bc0.tar.gz rneovim-e63538f21c90112faafc65ae12766d1f9abd5bc0.tar.bz2 rneovim-e63538f21c90112faafc65ae12766d1f9abd5bc0.zip |
Merge pull request #20198 from zeertzjq/cursorhold
fix(events): make CursorHold behave as documented
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/getchar.c | 2 | ||||
-rw-r--r-- | src/nvim/os/input.c | 24 | ||||
-rw-r--r-- | src/nvim/state.c | 2 |
3 files changed, 24 insertions, 4 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index c93810df8d..fd0acce25f 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1666,7 +1666,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) if (!char_avail()) { // flush output before waiting ui_flush(); - (void)os_inchar(NULL, 0, -1, 0, main_loop.events); + (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events); if (!multiqueue_empty(main_loop.events)) { state_handle_k_event(); continue; diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index ea9f31d776..8fc4a5dce5 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -38,6 +38,8 @@ static RBuffer *input_buffer = NULL; static bool input_eof = false; static int global_fd = -1; static bool blocking = false; +static int cursorhold_time = 0; ///< time waiting for CursorHold event +static int cursorhold_tb_change_cnt = 0; ///< tb_change_cnt when waiting started #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/input.c.generated.h" @@ -97,13 +99,25 @@ static void create_cursorhold_event(bool events_enabled) multiqueue_put(main_loop.events, cursorhold_event, 0); } +static void restart_cursorhold_wait(int tb_change_cnt) +{ + cursorhold_time = 0; + cursorhold_tb_change_cnt = tb_change_cnt; +} + /// Low level input function /// /// wait until either the input buffer is non-empty or, if `events` is not NULL /// until `events` is non-empty. int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events) { + // This check is needed so that feeding typeahead from RPC can prevent CursorHold. + if (tb_change_cnt != cursorhold_tb_change_cnt) { + restart_cursorhold_wait(tb_change_cnt); + } + if (maxlen && rbuffer_size(input_buffer)) { + restart_cursorhold_wait(tb_change_cnt); return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen); } @@ -118,18 +132,23 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e return 0; } } else { - if ((result = inbuf_poll((int)p_ut, events)) == kInputNone) { + uint64_t wait_start = os_hrtime(); + assert((int)p_ut >= cursorhold_time); + if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kInputNone) { if (read_stream.closed && silent_mode) { // Drained eventloop & initial input; exit silent/batch-mode (-es/-Es). read_error_exit(); } - + restart_cursorhold_wait(tb_change_cnt); if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) { create_cursorhold_event(events == main_loop.events); } else { before_blocking(); result = inbuf_poll(-1, events); } + } else { + cursorhold_time += (int)((os_hrtime() - wait_start) / 1000000); + cursorhold_time = MIN(cursorhold_time, (int)p_ut); } } @@ -141,6 +160,7 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e } if (maxlen && rbuffer_size(input_buffer)) { + restart_cursorhold_wait(tb_change_cnt); // Safe to convert rbuffer_read to int, it will never overflow since we use // relatively small buffers. return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen); diff --git a/src/nvim/state.c b/src/nvim/state.c index 458eed960f..8b07c484e6 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -65,7 +65,7 @@ getkey: // Call `os_inchar` directly to block for events or user input without // consuming anything from `input_buffer`(os/input.c) or calling the // mapping engine. - (void)os_inchar(NULL, 0, -1, 0, main_loop.events); + (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events); // If an event was put into the queue, we send K_EVENT directly. if (!multiqueue_empty(main_loop.events)) { key = K_EVENT; |