mirror of
https://github.com/neovim/neovim.git
synced 2025-10-01 23:48:32 +00:00
feat(tui): use DA1 response to determine OSC 52 support
Many terminals now include support for OSC 52 in their Primary Device Attributes (DA1) response. This is preferable to using XTGETTCAP because DA1 is _much_ more broadly supported.
This commit is contained in:
@@ -543,7 +543,7 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
|
||||
///
|
||||
/// The following terminal events are supported:
|
||||
///
|
||||
/// - "termresponse": The terminal sent an OSC, DCS, or APC response sequence to
|
||||
/// - "termresponse": The terminal sent a DA1, OSC, DCS, or APC response sequence to
|
||||
/// Nvim. The payload is the received response. Sets
|
||||
/// |v:termresponse| and fires |TermResponse|.
|
||||
///
|
||||
|
@@ -577,7 +577,7 @@ static size_t handle_bracketed_paste(TermInput *input, const char *ptr, size_t s
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Handle an OSC or DCS response sequence from the terminal.
|
||||
/// Handle an OSC, DCS, or APC response sequence from the terminal.
|
||||
static void handle_term_response(TermInput *input, const TermKeyKey *key)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
@@ -622,6 +622,47 @@ static void handle_term_response(TermInput *input, const TermKeyKey *key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a Primary Device Attributes (DA1) response from the terminal.
|
||||
static void handle_primary_device_attr(TermInput *input, TermKeyCsiParam *params, size_t nparams)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (input->callbacks.primary_device_attr) {
|
||||
void (*cb_save)(TUIData *) = input->callbacks.primary_device_attr;
|
||||
// Clear the callback before invoking it, as it may set a new callback. #34031
|
||||
input->callbacks.primary_device_attr = NULL;
|
||||
cb_save(input->tui_data);
|
||||
}
|
||||
|
||||
if (nparams == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MAXSIZE_TEMP_ARRAY(args, 2);
|
||||
ADD_C(args, STATIC_CSTR_AS_OBJ("termresponse"));
|
||||
|
||||
StringBuilder response = KV_INITIAL_VALUE;
|
||||
kv_concat(response, "\x1b[?");
|
||||
|
||||
for (size_t i = 0; i < nparams; i++) {
|
||||
int arg;
|
||||
if (termkey_interpret_csi_param(params[i], &arg, NULL, NULL) != TERMKEY_RES_KEY) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
kv_printf(response, "%d", arg);
|
||||
if (i < nparams - 1) {
|
||||
kv_push(response, ';');
|
||||
}
|
||||
}
|
||||
|
||||
kv_push(response, 'c');
|
||||
|
||||
ADD_C(args, STRING_OBJ(cbuf_as_string(response.items, response.size)));
|
||||
rpc_send_event(ui_client_channel_id, "nvim_ui_term_event", args);
|
||||
out:
|
||||
kv_destroy(response);
|
||||
}
|
||||
|
||||
/// Handle a mode report (DECRPM) sequence from the terminal.
|
||||
static void handle_modereport(TermInput *input, const TermKeyKey *key)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
@@ -668,13 +709,7 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key)
|
||||
switch (initial) {
|
||||
case '?':
|
||||
// Primary Device Attributes (DA1) response
|
||||
if (input->callbacks.primary_device_attr) {
|
||||
void (*cb_save)(TUIData *) = input->callbacks.primary_device_attr;
|
||||
// Clear the callback before invoking it, as it may set a new callback. #34031
|
||||
input->callbacks.primary_device_attr = NULL;
|
||||
cb_save(input->tui_data);
|
||||
}
|
||||
|
||||
handle_primary_device_attr(input, params, nparams);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@@ -17,6 +17,11 @@
|
||||
|
||||
#define strneq(a, b, n) (strncmp(a, b, n) == 0)
|
||||
|
||||
// Primary Device Attributes (DA1) response.
|
||||
// We make this a global (extern) variable so that we can override it with FFI
|
||||
// in tests.
|
||||
char vterm_primary_device_attr[] = "1;2;52";
|
||||
|
||||
// Some convenient wrappers to make callback functions easier
|
||||
|
||||
static void putglyph(VTermState *state, const schar_T schar, int width, VTermPos pos)
|
||||
@@ -1385,7 +1390,7 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
||||
val = CSI_ARG_OR(args[0], 0);
|
||||
if (val == 0) {
|
||||
// DEC VT100 response
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?1;2c");
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?%sc", vterm_primary_device_attr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
Reference in New Issue
Block a user