To: vim_dev@googlegroups.com Subject: Patch 8.1.1125 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1125 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. Files: src/libvterm/src/state.c, src/terminal.c, src/ui.c, src/proto/ui.pro, src/evalfunc.c, src/testdir/test_terminal.vim *** ../vim-8.1.1124/src/libvterm/src/state.c 2018-12-24 21:38:40.814173687 +0100 --- src/libvterm/src/state.c 2019-04-06 14:44:25.847900874 +0200 *************** *** 905,910 **** --- 905,911 ---- int leader_byte = 0; int intermed_byte = 0; VTermPos oldpos = state->pos; + int handled = 1; /* Some temporaries for later code */ int count, val; *************** *** 1416,1421 **** --- 1417,1426 ---- case 8: /* CSI 8 ; rows ; cols t set size */ if (argcount == 3) on_resize(CSI_ARG(args[1]), CSI_ARG(args[2]), state); + break; + default: + handled = 0; + break; } break; *************** *** 1450,1455 **** --- 1455,1465 ---- break; default: + handled = 0; + break; + } + + if (!handled) { if(state->fallbacks && state->fallbacks->csi) if((*state->fallbacks->csi)(leader, args, argcount, intermed, command, state->fbdata)) return 1; *** ../vim-8.1.1124/src/terminal.c 2019-03-30 18:46:57.360077328 +0100 --- src/terminal.c 2019-04-06 15:25:12.799197577 +0200 *************** *** 3842,3855 **** return 1; } static VTermParserCallbacks parser_fallbacks = { ! NULL, /* text */ ! NULL, /* control */ ! NULL, /* escape */ ! NULL, /* csi */ ! parse_osc, /* osc */ ! NULL, /* dcs */ ! NULL /* resize */ }; /* --- 3842,3909 ---- 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 = { ! NULL, // text ! NULL, // control ! NULL, // escape ! parse_csi, // csi ! parse_osc, // osc ! NULL, // dcs ! NULL // resize }; /* *** ../vim-8.1.1124/src/ui.c 2019-03-02 10:13:36.800974804 +0100 --- src/ui.c 2019-04-06 16:18:21.290945446 +0200 *************** *** 627,632 **** --- 627,653 ---- } } + #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 ui_breakcheck(void) { *** ../vim-8.1.1124/src/proto/ui.pro 2019-01-27 16:55:44.276707556 +0100 --- src/proto/ui.pro 2019-04-06 15:15:57.453489712 +0200 *************** *** 11,16 **** --- 11,17 ---- int ui_get_shellsize(void); void ui_set_shellsize(int mustset); void ui_new_shellsize(void); + int ui_get_winpos(int *x, int *y, varnumber_T timeout); void ui_breakcheck(void); void ui_breakcheck_force(int force); void clip_init(int can_use); *** ../vim-8.1.1124/src/evalfunc.c 2019-04-06 13:18:06.737335067 +0200 --- src/evalfunc.c 2019-04-06 16:18:24.146930813 +0200 *************** *** 5985,6004 **** if (rettv_list_alloc(rettv) == FAIL) return; ! #ifdef FEAT_GUI ! 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; if (argvars[0].v_type != VAR_UNKNOWN) timeout = tv_get_number(&argvars[0]); ! term_get_winpos(&x, &y, timeout); } #endif list_append_number(rettv->vval.v_list, (varnumber_T)x); --- 5985,5998 ---- if (rettv_list_alloc(rettv) == FAIL) return; ! #if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) { varnumber_T timeout = 100; if (argvars[0].v_type != VAR_UNKNOWN) timeout = tv_get_number(&argvars[0]); ! ! (void)ui_get_winpos(&x, &y, timeout); } #endif list_append_number(rettv->vval.v_list, (varnumber_T)x); *************** *** 6013,6033 **** f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! int x, y; ! ! if (gui_mch_get_winpos(&x, &y) == 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; } #endif --- 6007,6017 ---- f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; ! #if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) { int x, y; ! if (ui_get_winpos(&x, &y, 100) == OK) rettv->vval.v_number = x; } #endif *************** *** 6040,6060 **** f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! int x, y; ! ! if (gui_mch_get_winpos(&x, &y) == 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; } #endif --- 6024,6034 ---- f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv) { rettv->vval.v_number = -1; ! #if defined(FEAT_GUI) || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)) { int x, y; ! if (ui_get_winpos(&x, &y, 100) == OK) rettv->vval.v_number = y; } #endif *** ../vim-8.1.1125/src/testdir/test_terminal.vim 2019-04-06 12:39:47.439967638 +0200 --- src/testdir/test_terminal.vim 2019-04-06 17:22:33.203006052 +0200 *************** *** 1887,1889 **** --- 1887,1922 ---- au! BufLeave set statusline= 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\") + call StopVimInTerminal(buf) + call delete('XTest_getwinpos') + exe buf . 'bwipe!' + set splitright& + only! + endfunc *** ../vim-8.1.1124/src/version.c 2019-04-06 14:22:17.758642630 +0200 --- src/version.c 2019-04-06 17:24:10.354521046 +0200 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1125, /**/ -- hundred-and-one symptoms of being an internet addict: 214. Your MCI "Circle of Friends" are all Hayes-compatible. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///