# HG changeset patch # User Bram Moolenaar # Date 1639047605 -3600 # Node ID d413104a94c841041879529429e87d796ad6c439 # Parent 1ff39af446ad27b65f8dec23e65511983550dbdb patch 8.2.3763: when editing the cmdline a callback may cause a scroll up Commit: https://github.com/vim/vim/commit/e50507126f532a0b0ae65e201a6372b7ea5b0ccd Author: Bram Moolenaar Date: Thu Dec 9 10:51:05 2021 +0000 patch 8.2.3763: when editing the cmdline a callback may cause a scroll up Problem: When editing the command line a FocusLost callback may cause the screen to scroll up. Solution: Do not redraw at the last line but at the same place where the command line was before. (closes #9295) diff --git a/src/beval.c b/src/beval.c --- a/src/beval.c +++ b/src/beval.c @@ -308,7 +308,7 @@ general_beval_cb(BalloonEval *beval, int // The 'balloonexpr' evaluation may show something on the screen // that requires a screen update. if (must_redraw) - redraw_after_callback(FALSE); + redraw_after_callback(FALSE, FALSE); recursive = FALSE; return; diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -3205,7 +3205,7 @@ channel_close(channel_T *channel, int in if (channel_need_redraw) { channel_need_redraw = FALSE; - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } if (!channel->ch_drop_never) @@ -4687,7 +4687,7 @@ channel_parse_messages(void) if (channel_need_redraw) { channel_need_redraw = FALSE; - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } --safe_to_invoke_callback; diff --git a/src/drawscreen.c b/src/drawscreen.c --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -3019,14 +3019,19 @@ redraw_asap(int type) * it belongs. If highlighting was changed a redraw is needed. * If "call_update_screen" is FALSE don't call update_screen() when at the * command line. + * If "redraw_message" is TRUE. */ void -redraw_after_callback(int call_update_screen) +redraw_after_callback(int call_update_screen, int do_message) { ++redrawing_for_callback; - if (State == HITRETURN || State == ASKMORE) - ; // do nothing + if (State == HITRETURN || State == ASKMORE || State == SETWSIZE + || State == EXTERNCMD || State == CONFIRM || exmode_active) + { + if (do_message) + repeat_message(); + } else if (State & CMDLINE) { // Don't redraw when in prompt_for_number(). diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -3730,6 +3730,10 @@ redrawcmdline(void) redrawcmdline_ex(TRUE); } +/* + * When "do_compute_cmdrow" is TRUE the command line is redrawn at the bottom. + * If FALSE cmdline_row is used, which should redraw in the same place. + */ void redrawcmdline_ex(int do_compute_cmdrow) { diff --git a/src/job.c b/src/job.c --- a/src/job.c +++ b/src/job.c @@ -1260,7 +1260,7 @@ job_check_ended(void) if (channel_need_redraw) { channel_need_redraw = FALSE; - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } return did_end; } diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -3357,7 +3357,7 @@ popup_do_filter(int c) // Reset got_int to avoid a function used in the statusline aborts. got_int = FALSE; - redraw_after_callback(FALSE); + redraw_after_callback(FALSE, FALSE); got_int |= save_got_int; } recursive = FALSE; diff --git a/src/proto/drawscreen.pro b/src/proto/drawscreen.pro --- a/src/proto/drawscreen.pro +++ b/src/proto/drawscreen.pro @@ -8,7 +8,7 @@ void update_curbuf(int type); void update_debug_sign(buf_T *buf, linenr_T lnum); void updateWindow(win_T *wp); int redraw_asap(int type); -void redraw_after_callback(int call_update_screen); +void redraw_after_callback(int call_update_screen, int do_message); void redraw_later(int type); void redraw_win_later(win_T *wp, int type); void redraw_later_clear(void); diff --git a/src/sound.c b/src/sound.c --- a/src/sound.c +++ b/src/sound.c @@ -173,7 +173,7 @@ invoke_sound_callback(void) delete_sound_callback(scb->scb_callback); vim_free(scb); } - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } static void @@ -327,7 +327,7 @@ sound_wndproc(HWND hwnd, UINT message, W clear_tv(&rettv); delete_sound_callback(p); - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } break; diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -1258,7 +1258,7 @@ write_to_term(buf_T *buffer, char_u *msg update_cursor(curbuf->b_term, TRUE); } else - redraw_after_callback(TRUE); + redraw_after_callback(TRUE, FALSE); } } diff --git a/src/testdir/dumps/Test_terminal_focus_1.dump b/src/testdir/dumps/Test_terminal_focus_1.dump --- a/src/testdir/dumps/Test_terminal_focus_1.dump +++ b/src/testdir/dumps/Test_terminal_focus_1.dump @@ -1,6 +1,6 @@ -> +0&#ffffff0@74 +>I+0&#ffffff0| |a|m| |l|o|s|t| @65 |~+0#4040ff13&| @73 |~| @73 |~| @73 |~| @73 -|I+0#0000000&| |a|m| |l|o|s|t| @65 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_terminal_focus_2.dump b/src/testdir/dumps/Test_terminal_focus_2.dump --- a/src/testdir/dumps/Test_terminal_focus_2.dump +++ b/src/testdir/dumps/Test_terminal_focus_2.dump @@ -1,6 +1,6 @@ -> +0&#ffffff0@74 +>I+0&#ffffff0| |a|m| |b|a|c|k| @65 |~+0#4040ff13&| @73 |~| @73 |~| @73 |~| @73 -|I+0#0000000&| |a|m| |b|a|c|k| @65 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_terminal_focus_3.dump b/src/testdir/dumps/Test_terminal_focus_3.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_terminal_focus_3.dump @@ -0,0 +1,6 @@ +|~+0#4040ff13#ffffff0| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|x@73 +@6> @68 diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -1135,8 +1135,8 @@ func Test_terminal_focus_events() let lines =<< trim END set term=xterm ttymouse=xterm2 - au FocusLost * echo 'I am lost' - au FocusGained * echo 'I am back' + au FocusLost * call setline(1, 'I am lost') | set nomod + au FocusGained * call setline(1, 'I am back') | set nomod " FIXME: sometimes this job hangs, exit after a couple of seconds call timer_start(2000, {id -> execute('qall')}) END @@ -1152,6 +1152,14 @@ func Test_terminal_focus_events() call TermWait(buf) call VerifyScreenDump(buf, 'Test_terminal_focus_2', {}) + " check that a command line being edited is redrawn in place + call term_sendkeys(buf, ":" .. repeat('x', 80)) + call TermWait(buf) + call feedkeys("\[O", "Lx!") + call TermWait(buf) + call VerifyScreenDump(buf, 'Test_terminal_focus_3', {}) + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) call delete('XtermFocus') let &term = save_term diff --git a/src/time.c b/src/time.c --- a/src/time.c +++ b/src/time.c @@ -595,7 +595,7 @@ check_due_timer(void) } if (did_one) - redraw_after_callback(need_update_screen); + redraw_after_callback(need_update_screen, FALSE); #ifdef FEAT_BEVAL_TERM if (bevalexpr_due_set) diff --git a/src/ui.c b/src/ui.c --- a/src/ui.c +++ b/src/ui.c @@ -1156,29 +1156,7 @@ ui_focus_change( : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf); if (need_redraw) - { - // Something was executed, make sure the cursor is put back where it - // belongs. - need_wait_return = FALSE; - - if (State & CMDLINE) - redrawcmdline(); - else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE - || State == EXTERNCMD || State == CONFIRM || exmode_active) - repeat_message(); - else if ((State & NORMAL) || (State & INSERT)) - { - if (must_redraw != 0) - update_screen(0); - setcursor(); - } - cursor_on(); // redrawing may have switched it off - out_flush_cursor(FALSE, TRUE); -# ifdef FEAT_GUI - if (gui.in_use) - gui_update_scrollbars(FALSE); -# endif - } + redraw_after_callback(TRUE, TRUE); // File may have been changed from 'readonly' to 'noreadonly' if (need_maketitle) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3763, +/**/ 3762, /**/ 3761,