aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/tui')
-rw-r--r--src/nvim/tui/input.c34
-rw-r--r--src/nvim/tui/input.h2
-rw-r--r--src/nvim/tui/terminfo.c4
-rw-r--r--src/nvim/tui/tui.c79
4 files changed, 86 insertions, 33 deletions
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 61a59bcf06..fbeca26274 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -15,7 +15,7 @@
#include "nvim/tui/input.h"
#include "nvim/tui/tui.h"
#include "nvim/vim.h"
-#ifdef WIN32
+#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
#include "nvim/event/rstream.h"
@@ -143,7 +143,7 @@ void tinput_init(TermInput *input, Loop *loop)
// If stdin is not a pty, switch to stderr. For cases like:
// echo q | nvim -es
// ls *.md | xargs nvim
-#ifdef WIN32
+#ifdef MSWIN
if (!os_isatty(input->in_fd)) {
input->in_fd = os_get_conin_fd();
}
@@ -159,14 +159,10 @@ void tinput_init(TermInput *input, Loop *loop)
term = ""; // termkey_new_abstract assumes non-null (#2745)
}
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
input->tk = termkey_new_abstract(term,
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
termkey_start(input->tk);
-#else
- input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8);
-#endif
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
@@ -233,12 +229,12 @@ static void tinput_wait_enqueue(void **argv)
if (ui_client_channel_id) {
Array args = ARRAY_DICT_INIT;
Error err = ERROR_INIT;
- ADD(args, STRING_OBJ(copy_string(keys)));
+ ADD(args, STRING_OBJ(copy_string(keys, NULL)));
// TODO(bfredl): could be non-blocking now with paste?
ArenaMem res_mem = NULL;
Object result = rpc_send_call(ui_client_channel_id, "nvim_input", args, &res_mem, &err);
consumed = result.type == kObjectTypeInteger ? (size_t)result.data.integer : 0;
- arena_mem_free(res_mem, NULL);
+ arena_mem_free(res_mem);
} else {
consumed = input_enqueue(keys);
}
@@ -398,8 +394,16 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
button = last_pressed_button;
}
- if (button == 0 || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG
- && ev != TERMKEY_MOUSE_RELEASE)) {
+ if (ev == TERMKEY_MOUSE_UNKNOWN && !(key->code.mouse[0] & 0x20)) {
+ int code = key->code.mouse[0] & ~0x3c;
+ if (code == 66 || code == 67) {
+ ev = TERMKEY_MOUSE_PRESS;
+ button = code - 60;
+ }
+ }
+
+ if ((button == 0 && ev != TERMKEY_MOUSE_RELEASE)
+ || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG && ev != TERMKEY_MOUSE_RELEASE)) {
return;
}
@@ -431,8 +435,11 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
if (button == 4) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelUp");
} else if (button == 5) {
- len += (size_t)snprintf(buf + len, sizeof(buf) - len,
- "ScrollWheelDown");
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelDown");
+ } else if (button == 6) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelLeft");
+ } else if (button == 7) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "ScrollWheelRight");
} else {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Mouse");
last_pressed_button = button;
@@ -442,7 +449,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Drag");
break;
case TERMKEY_MOUSE_RELEASE:
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Release");
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, button ? "Release" : "MouseMove");
+ last_pressed_button = 0;
break;
case TERMKEY_MOUSE_UNKNOWN:
abort();
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 51df57938c..0b60394850 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -26,9 +26,7 @@ typedef struct term_input {
ExtkeysType extkeys_type;
long ttimeoutlen;
TermKey *tk;
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
-#endif
TimeWatcher timer_handle;
Loop *loop;
Stream read_stream;
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index ce48059b94..229e340dc3 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -189,7 +189,7 @@ void terminfo_info_msg(const unibi_term *const ut)
msg_printf_attr(0, " %-25s %-10s = ", unibi_name_str(i),
unibi_short_name_str(i));
// Most of these strings will contain escape sequences.
- msg_outtrans_special((char_u *)s, false, 0);
+ msg_outtrans_special(s, false, 0);
msg_putchar('\n');
}
}
@@ -216,7 +216,7 @@ void terminfo_info_msg(const unibi_term *const ut)
msg_puts("Extended string capabilities:\n");
for (size_t i = 0; i < unibi_count_ext_str(ut); i++) {
msg_printf_attr(0, " %-25s = ", unibi_get_ext_str_name(ut, i));
- msg_outtrans_special((char_u *)unibi_get_ext_str(ut, i), false, 0);
+ msg_outtrans_special(unibi_get_ext_str(ut, i), false, 0);
msg_putchar('\n');
}
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 38e8c15762..1cb1c34ad3 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -13,13 +13,13 @@
# include <termios.h>
#endif
+#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/ascii.h"
#include "nvim/event/loop.h"
#include "nvim/event/signal.h"
#include "nvim/highlight.h"
-#include "nvim/lib/kvec.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/map.h"
@@ -31,7 +31,7 @@
#include "nvim/os/tty.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
-#ifdef WIN32
+#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
#include "nvim/cursor_shape.h"
@@ -103,6 +103,7 @@ struct TUIData {
bool immediate_wrap_after_last_column;
bool bce;
bool mouse_enabled;
+ bool mouse_move_enabled;
bool busy, is_invisible, want_invisible;
bool cork, overflow;
bool cursor_color_changed;
@@ -117,6 +118,7 @@ struct TUIData {
ModeShape showing_mode;
struct {
int enable_mouse, disable_mouse;
+ int enable_mouse_move, disable_mouse_move;
int enable_bracketed_paste, disable_bracketed_paste;
int enable_lr_margin, disable_lr_margin;
int enter_strikethrough_mode;
@@ -236,6 +238,8 @@ static void terminfo_start(UI *ui)
data->showing_mode = SHAPE_IDX_N;
data->unibi_ext.enable_mouse = -1;
data->unibi_ext.disable_mouse = -1;
+ data->unibi_ext.enable_mouse_move = -1;
+ data->unibi_ext.disable_mouse_move = -1;
data->unibi_ext.set_cursor_color = -1;
data->unibi_ext.reset_cursor_color = -1;
data->unibi_ext.enable_bracketed_paste = -1;
@@ -259,7 +263,7 @@ static void terminfo_start(UI *ui)
data->input.tui_data = data;
const char *term = os_getenv("TERM");
-#ifdef WIN32
+#ifdef MSWIN
os_tty_guess_term(&term, data->out_fd);
os_setenv("TERM", term, 1);
// Old os_getenv() pointer is invalid after os_setenv(), fetch it again.
@@ -349,7 +353,7 @@ static void terminfo_start(UI *ui)
if (ret) {
ELOG("uv_tty_init failed: %s", uv_strerror(ret));
}
-#ifdef WIN32
+#ifdef MSWIN
ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW);
if (ret) {
ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret));
@@ -481,9 +485,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
// TODO(bfredl): zero hl is empty, send this explicitly?
kv_push(data->attrs, HLATTRS_INIT);
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
-#endif
tinput_init(&data->input, &tui_loop);
tui_terminal_start(ui);
@@ -1138,6 +1140,9 @@ static void tui_mouse_on(UI *ui)
TUIData *data = ui->data;
if (!data->mouse_enabled) {
unibi_out_ext(ui, data->unibi_ext.enable_mouse);
+ if (data->mouse_move_enabled) {
+ unibi_out_ext(ui, data->unibi_ext.enable_mouse_move);
+ }
data->mouse_enabled = true;
}
}
@@ -1146,6 +1151,9 @@ static void tui_mouse_off(UI *ui)
{
TUIData *data = ui->data;
if (data->mouse_enabled) {
+ if (data->mouse_move_enabled) {
+ unibi_out_ext(ui, data->unibi_ext.disable_mouse_move);
+ }
unibi_out_ext(ui, data->unibi_ext.disable_mouse);
data->mouse_enabled = false;
}
@@ -1405,13 +1413,16 @@ static void suspend_event(void **argv)
static void tui_suspend(UI *ui)
{
-#ifdef UNIX
TUIData *data = ui->data;
+#ifdef UNIX
// kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT
// before continuing. This is done in another callback to avoid
// loop_poll_events recursion
multiqueue_put_event(data->loop->fast_events,
event_create(suspend_event, 1, ui));
+#else
+ // Resume the main thread as suspending isn't implemented.
+ CONTINUE(data->bridge);
#endif
}
@@ -1457,9 +1468,18 @@ static void tui_screenshot(UI *ui, String path)
static void tui_option_set(UI *ui, String name, Object value)
{
TUIData *data = ui->data;
- if (strequal(name.data, "termguicolors")) {
+ if (strequal(name.data, "mousemoveevent")) {
+ if (data->mouse_move_enabled != value.data.boolean) {
+ if (data->mouse_enabled) {
+ tui_mouse_off(ui);
+ data->mouse_move_enabled = value.data.boolean;
+ tui_mouse_on(ui);
+ } else {
+ data->mouse_move_enabled = value.data.boolean;
+ }
+ }
+ } else if (strequal(name.data, "termguicolors")) {
ui->rgb = value.data.boolean;
-
data->print_attr_id = -1;
invalidate(ui, 0, data->grid.height, 0, data->grid.width);
} else if (strequal(name.data, "ttimeout")) {
@@ -1597,7 +1617,7 @@ static void unibi_goto(UI *ui, int row, int col)
memset(&vars, 0, sizeof(vars)); \
data->cork = true; \
retry: \
- unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \
+ unibi_format(vars, vars + 26, str, data->params, out, ui, pad, ui); \
if (data->overflow) { \
data->bufpos = orig_pos; \
flush_buf(ui); \
@@ -1628,6 +1648,7 @@ static void out(void *ctx, const char *str, size_t len)
if (len > available) {
if (data->cork) {
+ // Called by unibi_format(): avoid flush_buf() halfway an escape sequence.
data->overflow = true;
return;
} else {
@@ -1639,6 +1660,30 @@ static void out(void *ctx, const char *str, size_t len)
data->bufpos += len;
}
+/// Called by unibi_format() for padding instructions.
+/// The following parameter descriptions are extracted from unibi_format(3) and terminfo(5).
+///
+/// @param ctx the same as `ctx2` passed to unibi_format()
+/// @param delay the delay in tenths of milliseconds
+/// @param scale padding is proportional to the number of lines affected
+/// @param force padding is mandatory
+static void pad(void *ctx, size_t delay, int scale FUNC_ATTR_UNUSED, int force)
+{
+ if (!force) {
+ return;
+ }
+
+ UI *ui = ctx;
+ TUIData *data = ui->data;
+
+ if (data->overflow) {
+ return;
+ }
+
+ flush_buf(ui);
+ loop_uv_run(data->loop, (int)(delay / 10), false);
+}
+
static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, const char *val)
{
if (!unibi_get_str(ut, str)) {
@@ -1791,7 +1836,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
}
}
-#ifdef WIN32
+#ifdef MSWIN
// XXX: workaround libuv implicit LF => CRLF conversion. #10558
unibi_set_str(ut, unibi_cursor_down, "\x1b[B");
#endif
@@ -2135,13 +2180,17 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
"\x1b[?1002h\x1b[?1006h");
data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, "ext.disable_mouse",
"\x1b[?1002l\x1b[?1006l");
+ data->unibi_ext.enable_mouse_move = (int)unibi_add_ext_str(ut, "ext.enable_mouse_move",
+ "\x1b[?1003h");
+ data->unibi_ext.disable_mouse_move = (int)unibi_add_ext_str(ut, "ext.disable_mouse_move",
+ "\x1b[?1003l");
// Extended underline.
// terminfo will have Smulx for this (but no support for colors yet).
data->unibi_ext.set_underline_style = unibi_find_ext_str(ut, "Smulx");
if (data->unibi_ext.set_underline_style == -1) {
int ext_bool_Su = unibi_find_ext_bool(ut, "Su"); // used by kitty
- if (vte_version >= 5102
+ if (vte_version >= 5102 || konsolev >= 221170
|| (ext_bool_Su != -1
&& unibi_get_ext_bool(ut, (size_t)ext_bool_Su))) {
data->unibi_ext.set_underline_style = (int)unibi_add_ext_str(ut, "ext.set_underline_style",
@@ -2230,7 +2279,6 @@ static void flush_buf(UI *ui)
data->overflow = false;
}
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
/// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely
/// unreliable." (Vim, Bash, and tmux also do this.)
///
@@ -2239,14 +2287,14 @@ static void flush_buf(UI *ui)
static const char *tui_get_stty_erase(void)
{
static char stty_erase[2] = { 0 };
-# if defined(HAVE_TERMIOS_H)
+#if defined(HAVE_TERMIOS_H)
struct termios t;
if (tcgetattr(input_global_fd(), &t) != -1) {
stty_erase[0] = (char)t.c_cc[VERASE];
stty_erase[1] = '\0';
DLOG("stty/termios:erase=%s", stty_erase);
}
-# endif
+#endif
return stty_erase;
}
@@ -2280,4 +2328,3 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, void *d
return value;
}
-#endif