mirror of
https://github.com/neovim/neovim.git
synced 2025-01-01 17:23:36 -07:00
tui: defer termcodes using a timer
With this implementation there is no "jank" during startup.
Using the main_loop in any fashion is janky. Using only the TUI loop
emits the termcodes too soon, or requires bad hacks like counting
tui_flush invocations (9 seems to work).
ref #7664
ref #7649
ref #7664
ref 27f9b1c7b0
This commit is contained in:
parent
6b51c72e0c
commit
ed92ece815
@ -563,9 +563,6 @@ int main(int argc, char **argv)
|
|||||||
(void)eval_has_provider("clipboard");
|
(void)eval_has_provider("clipboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!headless_mode) {
|
|
||||||
ui_builtin_after_startup();
|
|
||||||
}
|
|
||||||
TIME_MSG("before starting main loop");
|
TIME_MSG("before starting main loop");
|
||||||
ILOG("starting main loop");
|
ILOG("starting main loop");
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ typedef struct {
|
|||||||
UIBridgeData *bridge;
|
UIBridgeData *bridge;
|
||||||
Loop *loop;
|
Loop *loop;
|
||||||
bool stop;
|
bool stop;
|
||||||
|
uv_timer_t after_startup_timer;
|
||||||
unibi_var_t params[9];
|
unibi_var_t params[9];
|
||||||
char buf[OUTBUF_SIZE];
|
char buf[OUTBUF_SIZE];
|
||||||
size_t bufpos;
|
size_t bufpos;
|
||||||
@ -126,7 +127,6 @@ UI *tui_start(void)
|
|||||||
{
|
{
|
||||||
UI *ui = xcalloc(1, sizeof(UI));
|
UI *ui = xcalloc(1, sizeof(UI));
|
||||||
ui->stop = tui_stop;
|
ui->stop = tui_stop;
|
||||||
ui->after_startup = tui_after_startup;
|
|
||||||
ui->rgb = p_tgc;
|
ui->rgb = p_tgc;
|
||||||
ui->resize = tui_resize;
|
ui->resize = tui_resize;
|
||||||
ui->clear = tui_clear;
|
ui->clear = tui_clear;
|
||||||
@ -170,18 +170,6 @@ static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index,
|
|||||||
return unibi_run(str, data->params, buf, len);
|
return unibi_run(str, data->params, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits some termcodes after Nvim startup, which were observed to slowdown
|
|
||||||
/// rendering during startup in tmux 2.3 (+focus-events). #7649
|
|
||||||
static void terminfo_after_startup_event(void **argv)
|
|
||||||
{
|
|
||||||
UI *ui = argv[0];
|
|
||||||
TUIData *data = ui->data;
|
|
||||||
// Enable bracketed paste
|
|
||||||
unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste);
|
|
||||||
// Enable focus reporting
|
|
||||||
unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void termname_set_event(void **argv)
|
static void termname_set_event(void **argv)
|
||||||
{
|
{
|
||||||
char *termname = argv[0];
|
char *termname = argv[0];
|
||||||
@ -261,6 +249,9 @@ static void terminfo_start(UI *ui)
|
|||||||
unibi_out(ui, unibi_enter_ca_mode);
|
unibi_out(ui, unibi_enter_ca_mode);
|
||||||
unibi_out(ui, unibi_keypad_xmit);
|
unibi_out(ui, unibi_keypad_xmit);
|
||||||
unibi_out(ui, unibi_clear_screen);
|
unibi_out(ui, unibi_clear_screen);
|
||||||
|
// Enable bracketed paste
|
||||||
|
unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste);
|
||||||
|
|
||||||
uv_loop_init(&data->write_loop);
|
uv_loop_init(&data->write_loop);
|
||||||
if (data->out_isatty) {
|
if (data->out_isatty) {
|
||||||
uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
|
uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
|
||||||
@ -275,13 +266,6 @@ static void terminfo_start(UI *ui)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tui_after_startup(UI *ui)
|
|
||||||
{
|
|
||||||
TUIData *data = ui->data;
|
|
||||||
loop_schedule(data->loop,
|
|
||||||
event_create(terminfo_after_startup_event, 1, ui));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void terminfo_stop(UI *ui)
|
static void terminfo_stop(UI *ui)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
@ -307,6 +291,18 @@ static void terminfo_stop(UI *ui)
|
|||||||
unibi_destroy(data->ut);
|
unibi_destroy(data->ut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void after_startup_timer_cb(uv_timer_t *handle)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
UI *ui = handle->data;
|
||||||
|
TUIData *data = ui->data;
|
||||||
|
uv_timer_stop(&data->after_startup_timer);
|
||||||
|
|
||||||
|
// Emit this after Nvim startup, not during. This works around a tmux
|
||||||
|
// 2.3 bug(?) which caused slow drawing during startup. #7649
|
||||||
|
unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting);
|
||||||
|
}
|
||||||
|
|
||||||
static void tui_terminal_start(UI *ui)
|
static void tui_terminal_start(UI *ui)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
@ -316,6 +312,8 @@ static void tui_terminal_start(UI *ui)
|
|||||||
update_size(ui);
|
update_size(ui);
|
||||||
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
|
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
|
||||||
term_input_start(&data->input);
|
term_input_start(&data->input);
|
||||||
|
|
||||||
|
uv_timer_start(&data->after_startup_timer, after_startup_timer_cb, 500, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tui_terminal_stop(UI *ui)
|
static void tui_terminal_stop(UI *ui)
|
||||||
@ -349,6 +347,8 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
|
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
|
||||||
#endif
|
#endif
|
||||||
|
uv_timer_init(&data->loop->uv, &data->after_startup_timer);
|
||||||
|
data->after_startup_timer.data = ui;
|
||||||
|
|
||||||
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
|
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
|
||||||
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
|
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
|
||||||
@ -367,6 +367,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_close((uv_handle_t *)&data->after_startup_timer, NULL);
|
||||||
ui_bridge_stopped(bridge);
|
ui_bridge_stopped(bridge);
|
||||||
term_input_destroy(&data->input);
|
term_input_destroy(&data->input);
|
||||||
signal_watcher_stop(&data->cont_handle);
|
signal_watcher_stop(&data->cont_handle);
|
||||||
|
@ -138,14 +138,6 @@ void ui_builtin_start(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Immediately after VimEnter event.
|
|
||||||
void ui_builtin_after_startup(void)
|
|
||||||
{
|
|
||||||
#ifdef FEAT_TUI
|
|
||||||
UI_CALL(after_startup);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_builtin_stop(void)
|
void ui_builtin_stop(void)
|
||||||
{
|
{
|
||||||
UI_CALL(stop);
|
UI_CALL(stop);
|
||||||
|
@ -36,7 +36,6 @@ struct ui_t {
|
|||||||
#endif
|
#endif
|
||||||
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
|
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
|
||||||
void (*stop)(UI *ui);
|
void (*stop)(UI *ui);
|
||||||
void (*after_startup)(UI *ui);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
@ -42,7 +42,6 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
|
|||||||
rv->ui = ui;
|
rv->ui = ui;
|
||||||
rv->bridge.rgb = ui->rgb;
|
rv->bridge.rgb = ui->rgb;
|
||||||
rv->bridge.stop = ui_bridge_stop;
|
rv->bridge.stop = ui_bridge_stop;
|
||||||
rv->bridge.after_startup = ui_bridge_after_startup;
|
|
||||||
rv->bridge.resize = ui_bridge_resize;
|
rv->bridge.resize = ui_bridge_resize;
|
||||||
rv->bridge.clear = ui_bridge_clear;
|
rv->bridge.clear = ui_bridge_clear;
|
||||||
rv->bridge.eol_clear = ui_bridge_eol_clear;
|
rv->bridge.eol_clear = ui_bridge_eol_clear;
|
||||||
@ -107,16 +106,6 @@ static void ui_thread_run(void *data)
|
|||||||
bridge->ui_main(bridge, bridge->ui);
|
bridge->ui_main(bridge, bridge->ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_bridge_after_startup(UI *b)
|
|
||||||
{
|
|
||||||
UI_BRIDGE_CALL(b, after_startup, 1, b);
|
|
||||||
}
|
|
||||||
static void ui_bridge_after_startup_event(void **argv)
|
|
||||||
{
|
|
||||||
UI *ui = UI(argv[0]);
|
|
||||||
ui->after_startup(ui);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ui_bridge_stop(UI *b)
|
static void ui_bridge_stop(UI *b)
|
||||||
{
|
{
|
||||||
UIBridgeData *bridge = (UIBridgeData *)b;
|
UIBridgeData *bridge = (UIBridgeData *)b;
|
||||||
|
Loading…
Reference in New Issue
Block a user