mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.1125: libvterm does not handle the window position report
Problem: Libvterm does not handle the window position report. Solution: Let libvterm call the fallback CSI handler when not handling CSI sequence. Handle the window position report in Vim.
This commit is contained in:
parent
d9eefe3155
commit
fa1e90cd4d
@ -5985,20 +5985,14 @@ f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
|
|
||||||
if (rettv_list_alloc(rettv) == FAIL)
|
if (rettv_list_alloc(rettv) == FAIL)
|
||||||
return;
|
return;
|
||||||
#ifdef FEAT_GUI
|
#if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE))
|
||||||
if (gui.in_use)
|
|
||||||
(void)gui_mch_get_winpos(&x, &y);
|
|
||||||
# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
|
|
||||||
else
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
|
|
||||||
{
|
{
|
||||||
varnumber_T timeout = 100;
|
varnumber_T timeout = 100;
|
||||||
|
|
||||||
if (argvars[0].v_type != VAR_UNKNOWN)
|
if (argvars[0].v_type != VAR_UNKNOWN)
|
||||||
timeout = tv_get_number(&argvars[0]);
|
timeout = tv_get_number(&argvars[0]);
|
||||||
term_get_winpos(&x, &y, timeout);
|
|
||||||
|
(void)ui_get_winpos(&x, &y, timeout);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
list_append_number(rettv->vval.v_list, (varnumber_T)x);
|
list_append_number(rettv->vval.v_list, (varnumber_T)x);
|
||||||
@ -6013,21 +6007,11 @@ f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
|
f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
|
||||||
{
|
{
|
||||||
rettv->vval.v_number = -1;
|
rettv->vval.v_number = -1;
|
||||||
#ifdef FEAT_GUI
|
#if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE))
|
||||||
if (gui.in_use)
|
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (gui_mch_get_winpos(&x, &y) == OK)
|
if (ui_get_winpos(&x, &y, 100) == OK)
|
||||||
rettv->vval.v_number = x;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
if (term_get_winpos(&x, &y, (varnumber_T)100) == OK)
|
|
||||||
rettv->vval.v_number = x;
|
rettv->vval.v_number = x;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -6040,21 +6024,11 @@ f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
|
f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
|
||||||
{
|
{
|
||||||
rettv->vval.v_number = -1;
|
rettv->vval.v_number = -1;
|
||||||
#ifdef FEAT_GUI
|
#if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE))
|
||||||
if (gui.in_use)
|
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (gui_mch_get_winpos(&x, &y) == OK)
|
if (ui_get_winpos(&x, &y, 100) == OK)
|
||||||
rettv->vval.v_number = y;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
if (term_get_winpos(&x, &y, (varnumber_T)100) == OK)
|
|
||||||
rettv->vval.v_number = y;
|
rettv->vval.v_number = y;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -905,6 +905,7 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
|||||||
int leader_byte = 0;
|
int leader_byte = 0;
|
||||||
int intermed_byte = 0;
|
int intermed_byte = 0;
|
||||||
VTermPos oldpos = state->pos;
|
VTermPos oldpos = state->pos;
|
||||||
|
int handled = 1;
|
||||||
|
|
||||||
/* Some temporaries for later code */
|
/* Some temporaries for later code */
|
||||||
int count, val;
|
int count, val;
|
||||||
@ -1416,6 +1417,10 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
|||||||
case 8: /* CSI 8 ; rows ; cols t set size */
|
case 8: /* CSI 8 ; rows ; cols t set size */
|
||||||
if (argcount == 3)
|
if (argcount == 3)
|
||||||
on_resize(CSI_ARG(args[1]), CSI_ARG(args[2]), state);
|
on_resize(CSI_ARG(args[1]), CSI_ARG(args[2]), state);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handled = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1450,6 +1455,11 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
handled = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
if(state->fallbacks && state->fallbacks->csi)
|
if(state->fallbacks && state->fallbacks->csi)
|
||||||
if((*state->fallbacks->csi)(leader, args, argcount, intermed, command, state->fbdata))
|
if((*state->fallbacks->csi)(leader, args, argcount, intermed, command, state->fbdata))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -11,6 +11,7 @@ void suspend_shell(void);
|
|||||||
int ui_get_shellsize(void);
|
int ui_get_shellsize(void);
|
||||||
void ui_set_shellsize(int mustset);
|
void ui_set_shellsize(int mustset);
|
||||||
void ui_new_shellsize(void);
|
void ui_new_shellsize(void);
|
||||||
|
int ui_get_winpos(int *x, int *y, varnumber_T timeout);
|
||||||
void ui_breakcheck(void);
|
void ui_breakcheck(void);
|
||||||
void ui_breakcheck_force(int force);
|
void ui_breakcheck_force(int force);
|
||||||
void clip_init(int can_use);
|
void clip_init(int can_use);
|
||||||
|
@ -3842,14 +3842,68 @@ parse_osc(const char *command, size_t cmdlen, void *user)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called by libvterm when it cannot recognize a CSI sequence.
|
||||||
|
* We recognize the window position report.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_csi(
|
||||||
|
const char *leader UNUSED,
|
||||||
|
const long args[],
|
||||||
|
int argcount,
|
||||||
|
const char *intermed UNUSED,
|
||||||
|
char command,
|
||||||
|
void *user)
|
||||||
|
{
|
||||||
|
term_T *term = (term_T *)user;
|
||||||
|
char buf[100];
|
||||||
|
int len;
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
win_T *wp;
|
||||||
|
|
||||||
|
// We recognize only CSI 13 t
|
||||||
|
if (command != 't' || argcount != 1 || args[0] != 13)
|
||||||
|
return 0; // not handled
|
||||||
|
|
||||||
|
// When getting the window position fails it results in zero/zero.
|
||||||
|
(void)ui_get_winpos(&x, &y, (varnumber_T)100);
|
||||||
|
|
||||||
|
FOR_ALL_WINDOWS(wp)
|
||||||
|
if (wp->w_buffer == term->tl_buffer)
|
||||||
|
break;
|
||||||
|
if (wp != NULL)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_GUI
|
||||||
|
if (gui.in_use)
|
||||||
|
{
|
||||||
|
x += wp->w_wincol * gui.char_width;
|
||||||
|
y += W_WINROW(wp) * gui.char_height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// We roughly estimate the position of the terminal window inside
|
||||||
|
// the Vim window by assuing a 10 x 7 character cell.
|
||||||
|
x += wp->w_wincol * 7;
|
||||||
|
y += W_WINROW(wp) * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = vim_snprintf(buf, 100, "\x1b[3;%d;%dt", x, y);
|
||||||
|
channel_send(term->tl_job->jv_channel, get_tty_part(term),
|
||||||
|
(char_u *)buf, len, NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static VTermParserCallbacks parser_fallbacks = {
|
static VTermParserCallbacks parser_fallbacks = {
|
||||||
NULL, /* text */
|
NULL, // text
|
||||||
NULL, /* control */
|
NULL, // control
|
||||||
NULL, /* escape */
|
NULL, // escape
|
||||||
NULL, /* csi */
|
parse_csi, // csi
|
||||||
parse_osc, /* osc */
|
parse_osc, // osc
|
||||||
NULL, /* dcs */
|
NULL, // dcs
|
||||||
NULL /* resize */
|
NULL // resize
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1887,3 +1887,36 @@ func Test_terminal_statusline()
|
|||||||
au! BufLeave
|
au! BufLeave
|
||||||
set statusline=
|
set statusline=
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_terminal_getwinpos()
|
||||||
|
" split, go to the bottom-right window
|
||||||
|
split
|
||||||
|
wincmd j
|
||||||
|
set splitright
|
||||||
|
|
||||||
|
call writefile([
|
||||||
|
\ 'echo getwinpos()',
|
||||||
|
\ ], 'XTest_getwinpos')
|
||||||
|
let buf = RunVimInTerminal('-S XTest_getwinpos', {'cols': 60})
|
||||||
|
call term_wait(buf)
|
||||||
|
|
||||||
|
" Find the output of getwinpos() in the bottom line.
|
||||||
|
let rows = term_getsize(buf)[0]
|
||||||
|
call WaitForAssert({-> assert_match('\[\d\+, \d\+\]', term_getline(buf, rows))})
|
||||||
|
let line = term_getline(buf, rows)
|
||||||
|
let xpos = str2nr(substitute(line, '\[\(\d\+\), \d\+\]', '\1', ''))
|
||||||
|
let ypos = str2nr(substitute(line, '\[\d\+, \(\d\+\)\]', '\1', ''))
|
||||||
|
|
||||||
|
" Position must be bigger than the getwinpos() result of Vim itself.
|
||||||
|
let [xroot, yroot] = getwinpos()
|
||||||
|
call assert_inrange(xroot + 2, xroot + 1000, xpos)
|
||||||
|
call assert_inrange(yroot + 2, yroot + 1000, ypos)
|
||||||
|
|
||||||
|
call term_wait(buf)
|
||||||
|
call term_sendkeys(buf, ":q\<CR>")
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XTest_getwinpos')
|
||||||
|
exe buf . 'bwipe!'
|
||||||
|
set splitright&
|
||||||
|
only!
|
||||||
|
endfunc
|
||||||
|
21
src/ui.c
21
src/ui.c
@ -627,6 +627,27 @@ ui_new_shellsize(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(FEAT_EVAL) \
|
||||||
|
&& (defined(FEAT_GUI) \
|
||||||
|
|| (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)))) \
|
||||||
|
|| defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Get the window position in pixels, if possible.
|
||||||
|
* Return FAIL when not possible.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ui_get_winpos(int *x, int *y, varnumber_T timeout)
|
||||||
|
{
|
||||||
|
# ifdef FEAT_GUI
|
||||||
|
if (gui.in_use)
|
||||||
|
return gui_mch_get_winpos(x, y);
|
||||||
|
# endif
|
||||||
|
# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
|
||||||
|
return term_get_winpos(x, y, timeout);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
ui_breakcheck(void)
|
ui_breakcheck(void)
|
||||||
{
|
{
|
||||||
|
@ -771,6 +771,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1125,
|
||||||
/**/
|
/**/
|
||||||
1124,
|
1124,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user