changeset 26466:d413104a94c8 v8.2.3763

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 <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 Dec 2021 12:00:05 +0100
parents 1ff39af446ad
children 25348fc7dfb6
files src/beval.c src/channel.c src/drawscreen.c src/ex_getln.c src/job.c src/popupwin.c src/proto/drawscreen.pro src/sound.c src/terminal.c src/testdir/dumps/Test_terminal_focus_1.dump src/testdir/dumps/Test_terminal_focus_2.dump src/testdir/dumps/Test_terminal_focus_3.dump src/testdir/test_terminal.vim src/time.c src/ui.c src/version.c
diffstat 16 files changed, 45 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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;
--- 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().
--- 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)
 {
--- 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;
 }
--- 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;
--- 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);
--- 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;
--- 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);
     }
 }
 
--- 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| 
--- 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| 
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
--- 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("\<Esc>[O", "Lx!")
+  call TermWait(buf)
+  call VerifyScreenDump(buf, 'Test_terminal_focus_3', {})
+  call term_sendkeys(buf, "\<Esc>")
+
   call StopVimInTerminal(buf)
   call delete('XtermFocus')
   let &term = save_term
--- 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)
--- 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)
--- 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,