0
0
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:
Bram Moolenaar 2019-04-06 17:47:40 +02:00
parent d9eefe3155
commit fa1e90cd4d
7 changed files with 135 additions and 40 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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
}; };
/* /*

View File

@ -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

View File

@ -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)
{ {

View File

@ -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,
/**/ /**/