unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Po Lu <luangruo@yahoo.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: Allowing point to be outside the window?
Date: Mon, 06 Dec 2021 10:11:47 +0800	[thread overview]
Message-ID: <877dcipjmk.fsf@yahoo.com> (raw)
In-Reply-To: <83h7bn4e55.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 05 Dec 2021 11:03:34 +0200")

[-- Attachment #1: Type: text/plain, Size: 1240 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

> That'd cover scrolling a window in a way that leaves point outside of
> it.  But Emacs also sets the window-start position in other
> situations.  Moreover, the display engine itself does that, see
> redisplay_window.

> So some logic and/or flags will be needed to distinguish between the
> cases.

We should not recenter the display in any case where the start is not
forced and point is not moved.

>> For instance, we could enable the code that scrolls the window to follow
>> point if PT != w->point (if that makes sense).

> So any change in the numerical value of point will scroll the window
> to bring point into the view?  That'd be fine if that's what users
> expect.  But do they?  E.g., what happens if point is below the
> window, and you paste (with the mouse) some text into the visible
> portion of the window (which doesn't show point)?

That's not a problem, as `mouse-yank-primary' and friends already call
mouse-set-point.

WDYT about the attached patch?  It recenters the display whenever PT !=
w->last_point, and it seems to work very well.

It also introduces a new variable `scroll-move-point' that controls if
the scrolling commands will try to move point to stay visible.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: diff.diff --]
[-- Type: text/x-patch, Size: 22133 bytes --]

diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 15cad88d59..814f9d0286 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -250,10 +250,18 @@ Auto Scrolling
 @section Automatic Scrolling
 
 @cindex automatic scrolling
-  Emacs performs @dfn{automatic scrolling} when point moves out of the
-visible portion of the text.  Normally, automatic scrolling centers
-point vertically in the window, but there are several ways to alter
-this behavior.
+  Emacs by default performs @dfn{automatic scrolling} when point moves
+out of the visible portion of the text.  Normally, automatic scrolling
+centers point vertically in the window, but there are several ways to
+alter this behavior.
+
+@vindex keep-point-visible
+  If @code{keep-point-visible} is nil, redisplay will not move recenter
+the display when the window start is changed.
+
+@vindex scroll-move-point
+  If @code{scroll-move-point} is nil, scrolling commands will not move
+point to keep it inside the visible part of the window.
 
 @vindex scroll-conservatively
 @vindex scroll-minibuffer-conservatively
diff --git a/etc/NEWS b/etc/NEWS
index a8b7dc56ba..7154f20ade 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -257,6 +257,15 @@ are met.  The conditions are given by the argument, which can be
 
 * Editing Changes in Emacs 29.1
 
+** New variable 'keep-point-visible'.
+This variable controls if redisplay will try to keep point visible
+inside the window.
+
++++
+** New variable 'scroll-move-point'.
+This variable controls if scrolling moves point to stay inside the
+window.
+
 ---
 ** Indentation of 'cl-flet' and 'cl-labels' has changed.
 These forms now indent like this:
diff --git a/src/window.c b/src/window.c
index e801ff821f..c54f8164d3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5576,7 +5576,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
      something like (scroll-down 1) with PT in the line before
      the partially visible one would recenter.  */
 
-  if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
+  if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)
+      && scroll_move_point)
     {
       itdata = bidi_shelve_cache ();
       /* Move backward half the height of the window.  Performance note:
@@ -5657,8 +5658,9 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
 		  w->start_at_line_beg = true;
 		  wset_update_mode_line (w);
 		  /* Set force_start so that redisplay_window will run the
-		     window-scroll-functions.  */
-		  w->force_start = true;
+		     window-scroll-functions, unless scroll_move_point is false,
+		     in which case forcing the start will cause recentering.  */
+		  w->force_start = scroll_move_point;
 		  return;
 		}
 	    }
@@ -5842,8 +5844,9 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
       wset_update_mode_line (w);
       /* Set force_start so that redisplay_window will run the
-	 window-scroll-functions.  */
-      w->force_start = true;
+	 window-scroll-functions, unless scroll_move_point is false,
+	 in which case forcing the start will cause recentering.  */
+      w->force_start = scroll_move_point;
     }
 
   /* The rest of this function uses current_y in a nonstandard way,
@@ -5855,157 +5858,161 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
      even if there is a header line.  */
   this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
 
-  if (n > 0)
+  if (scroll_move_point)
     {
-      int last_y = it.last_visible_y - this_scroll_margin - 1;
-
-      /* We moved the window start towards ZV, so PT may be now
-	 in the scroll margin at the top.  */
-      move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
-      if (IT_CHARPOS (it) == PT
-	  && it.current_y >= this_scroll_margin
-	  && it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
-				    - WINDOW_HEADER_LINE_HEIGHT (w)
-	  && (NILP (Vscroll_preserve_screen_position)
-	      || EQ (Vscroll_preserve_screen_position, Qt)))
-	/* We found PT at a legitimate height.  Leave it alone.  */
-	;
-      else
+      if (n > 0)
 	{
-	  if (window_scroll_pixel_based_preserve_y >= 0)
-	    {
-	      /* Don't enter the scroll margin at the end of the window.  */
-	      int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
-
-	      /* If we have a header line, take account of it.  This
-		 is necessary because we set it.current_y to 0, above.  */
-	      move_it_to (&it, -1,
-			  window_scroll_pixel_based_preserve_x,
-			  goal_y - WINDOW_TAB_LINE_HEIGHT (w)
-				 - WINDOW_HEADER_LINE_HEIGHT (w),
-			  -1, MOVE_TO_Y | MOVE_TO_X);
-	    }
+	  int last_y = it.last_visible_y - this_scroll_margin - 1;
 
-	  /* Get out of the scroll margin at the top of the window.  */
-	  while (it.current_y < this_scroll_margin)
+	  /* We moved the window start towards ZV, so PT may be now
+	     in the scroll margin at the top.  */
+	  move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+	  if (IT_CHARPOS (it) == PT
+	      && it.current_y >= this_scroll_margin
+	      && it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
+	      - WINDOW_HEADER_LINE_HEIGHT (w)
+	      && (NILP (Vscroll_preserve_screen_position)
+		  || EQ (Vscroll_preserve_screen_position, Qt)))
+	    /* We found PT at a legitimate height.  Leave it alone.  */
+	    ;
+	  else
 	    {
-	      int prev = it.current_y;
-	      move_it_by_lines (&it, 1);
-	      if (prev == it.current_y)
-		break;
+	      if (window_scroll_pixel_based_preserve_y >= 0)
+		{
+		  /* Don't enter the scroll margin at the end of the window.  */
+		  int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
+
+		  /* If we have a header line, take account of it.  This
+		     is necessary because we set it.current_y to 0, above.  */
+		  move_it_to (&it, -1,
+			      window_scroll_pixel_based_preserve_x,
+			      goal_y - WINDOW_TAB_LINE_HEIGHT (w)
+			      - WINDOW_HEADER_LINE_HEIGHT (w),
+			      -1, MOVE_TO_Y | MOVE_TO_X);
+		}
+
+	      /* Get out of the scroll margin at the top of the window.  */
+	      while (it.current_y < this_scroll_margin)
+		{
+		  int prev = it.current_y;
+		  move_it_by_lines (&it, 1);
+		  if (prev == it.current_y)
+		    break;
+		}
+	      SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+	      /* Fix up the Y position to preserve, if it is inside the
+		 scroll margin at the window top.  */
+	      if (window_scroll_pixel_based_preserve_y >= 0
+		  && window_scroll_pixel_based_preserve_y < this_scroll_margin)
+		window_scroll_pixel_based_preserve_y = this_scroll_margin;
 	    }
-	  SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
-	  /* Fix up the Y position to preserve, if it is inside the
-	     scroll margin at the window top.  */
-	  if (window_scroll_pixel_based_preserve_y >= 0
-	      && window_scroll_pixel_based_preserve_y < this_scroll_margin)
-	    window_scroll_pixel_based_preserve_y = this_scroll_margin;
 	}
-    }
-  else if (n < 0)
-    {
-      ptrdiff_t charpos, bytepos;
-      bool partial_p;
-
-      /* Save our position, for the
-	 window_scroll_pixel_based_preserve_y case.  */
-      charpos = IT_CHARPOS (it);
-      bytepos = IT_BYTEPOS (it);
-
-      /* We moved the window start towards BEGV, so PT may be now
-	 in the scroll margin at the bottom.  */
-      move_it_to (&it, PT, -1,
-		  /* We subtract WINDOW_HEADER_LINE_HEIGHT because
-		     it.y is relative to the bottom of the header
-		     line, see above.  */
-		  (it.last_visible_y - WINDOW_TAB_LINE_HEIGHT (w)
-				     - WINDOW_HEADER_LINE_HEIGHT (w)
-		   - partial_line_height (&it) - this_scroll_margin - 1),
-		  -1,
-		  MOVE_TO_POS | MOVE_TO_Y);
-
-      /* Save our position, in case it's correct.  */
-      charpos = IT_CHARPOS (it);
-      bytepos = IT_BYTEPOS (it);
-
-      /* If PT is in the screen line at the last fully visible line,
-	 move_it_to will stop at X = 0 in that line, because the
-	 required Y coordinate is reached there.  See if we can get to
-	 PT without descending lower in Y, and if we can, it means we
-	 reached PT before the scroll margin.  */
-      if (charpos != PT)
+      else if (n < 0)
 	{
-	  struct it it2;
-	  void *it_data;
+	  ptrdiff_t charpos, bytepos;
+	  bool partial_p;
 
-	  it2 = it;
-	  it_data = bidi_shelve_cache ();
-	  move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
-	  if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
+	  /* Save our position, for the
+	     window_scroll_pixel_based_preserve_y case.  */
+	  charpos = IT_CHARPOS (it);
+	  bytepos = IT_BYTEPOS (it);
+
+	  /* We moved the window start towards BEGV, so PT may be now
+	     in the scroll margin at the bottom.  */
+	  move_it_to (&it, PT, -1,
+		      /* We subtract WINDOW_HEADER_LINE_HEIGHT because
+			 it.y is relative to the bottom of the header
+			 line, see above.  */
+		      (it.last_visible_y - WINDOW_TAB_LINE_HEIGHT (w)
+		       - WINDOW_HEADER_LINE_HEIGHT (w)
+		       - partial_line_height (&it) - this_scroll_margin - 1),
+		      -1,
+		      MOVE_TO_POS | MOVE_TO_Y);
+
+	  /* Save our position, in case it's correct.  */
+	  charpos = IT_CHARPOS (it);
+	  bytepos = IT_BYTEPOS (it);
+
+	  /* If PT is in the screen line at the last fully visible line,
+	     move_it_to will stop at X = 0 in that line, because the
+	     required Y coordinate is reached there.  See if we can get to
+	     PT without descending lower in Y, and if we can, it means we
+	     reached PT before the scroll margin.  */
+	  if (charpos != PT)
 	    {
-	      charpos = IT_CHARPOS (it);
-	      bytepos = IT_BYTEPOS (it);
-	      bidi_unshelve_cache (it_data, true);
+	      struct it it2;
+	      void *it_data;
+
+	      it2 = it;
+	      it_data = bidi_shelve_cache ();
+	      move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+	      if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
+		{
+		  charpos = IT_CHARPOS (it);
+		  bytepos = IT_BYTEPOS (it);
+		  bidi_unshelve_cache (it_data, true);
+		}
+	      else
+		{
+		  it = it2;
+		  bidi_unshelve_cache (it_data, false);
+		}
 	    }
+
+	  /* See if point is on a partially visible line at the end.  */
+	  if (it.what == IT_EOB)
+	    partial_p =
+	      it.current_y + it.ascent + it.descent
+	      > it.last_visible_y - this_scroll_margin
+	      - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
 	  else
 	    {
-	      it = it2;
-	      bidi_unshelve_cache (it_data, false);
+	      move_it_by_lines (&it, 1);
+	      partial_p =
+		it.current_y
+		> it.last_visible_y - this_scroll_margin
+		- WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
 	    }
-	}
-
-      /* See if point is on a partially visible line at the end.  */
-      if (it.what == IT_EOB)
-	partial_p =
-	  it.current_y + it.ascent + it.descent
-	  > it.last_visible_y - this_scroll_margin
-	  - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
-      else
-	{
-	  move_it_by_lines (&it, 1);
-	  partial_p =
-	    it.current_y
-	    > it.last_visible_y - this_scroll_margin
-	      - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
-	}
 
-      if (charpos == PT && !partial_p
-          && (NILP (Vscroll_preserve_screen_position)
-	      || EQ (Vscroll_preserve_screen_position, Qt)))
-	/* We found PT before we found the display margin, so PT is ok.  */
-	;
-      else if (window_scroll_pixel_based_preserve_y >= 0)
-	{
-	  int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
-			    window_scroll_pixel_based_preserve_y);
-
-	  /* Don't let the preserved screen Y coordinate put us inside
-	     any of the two margins.  */
-	  if (goal_y < this_scroll_margin)
-	    goal_y = this_scroll_margin;
-	  SET_TEXT_POS_FROM_MARKER (start, w->start);
-	  start_display (&it, w, start);
-	  /* It would be wrong to subtract WINDOW_HEADER_LINE_HEIGHT
-	     here because we called start_display again and did not
-	     alter it.current_y this time.  */
-	  move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
-		      goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
-	  SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
-	}
-      else
-	{
-	  if (partial_p)
-	    /* The last line was only partially visible, so back up two
-	       lines to make sure we're on a fully visible line.  */
+	  if (charpos == PT && !partial_p
+	      && (NILP (Vscroll_preserve_screen_position)
+		  || EQ (Vscroll_preserve_screen_position, Qt)))
+	    /* We found PT before we found the display margin, so PT is ok.  */
+	    ;
+	  else if (window_scroll_pixel_based_preserve_y >= 0)
 	    {
-	      move_it_by_lines (&it, -2);
+	      int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
+				window_scroll_pixel_based_preserve_y);
+
+	      /* Don't let the preserved screen Y coordinate put us inside
+		 any of the two margins.  */
+	      if (goal_y < this_scroll_margin)
+		goal_y = this_scroll_margin;
+	      SET_TEXT_POS_FROM_MARKER (start, w->start);
+	      start_display (&it, w, start);
+	      /* It would be wrong to subtract WINDOW_HEADER_LINE_HEIGHT
+		 here because we called start_display again and did not
+		 alter it.current_y this time.  */
+	      move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
+			  goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
 	      SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
 	    }
 	  else
-	    /* No, the position we saved is OK, so use it.  */
-	    SET_PT_BOTH (charpos, bytepos);
+	    {
+	      if (partial_p)
+		/* The last line was only partially visible, so back up two
+		   lines to make sure we're on a fully visible line.  */
+		{
+		  move_it_by_lines (&it, -2);
+		  SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+		}
+	      else
+		/* No, the position we saved is OK, so use it.  */
+		SET_PT_BOTH (charpos, bytepos);
+	    }
 	}
     }
+
   bidi_unshelve_cache (itdata, false);
 
   if (adjust_old_pointm)
@@ -8500,6 +8507,10 @@ syms_of_window (void)
 displayed after a scrolling operation to be somewhat inaccurate.  */);
   fast_but_imprecise_scrolling = false;
 
+  DEFVAR_BOOL ("scroll-move-point", scroll_move_point,
+	       doc: /* If nil, don't move point to fit inside the window when scrolling.  */);
+  scroll_move_point = true;
+
   defsubr (&Sselected_window);
   defsubr (&Sold_selected_window);
   defsubr (&Sminibuffer_window);
diff --git a/src/xdisp.c b/src/xdisp.c
index 0ff6286af7..d0d983ca97 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -16118,6 +16118,8 @@ #define AINC(a,i)							\
   tlbufpos = this_line_start_pos;
   tlendpos = this_line_end_pos;
   if (!consider_all_windows_p
+      /* TODO: enable this optimization.  */
+      && keep_point_visible
       && CHARPOS (tlbufpos) > 0
       && !w->update_mode_line
       && !current_buffer->clip_changed
@@ -17768,6 +17770,9 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
   else
     scroll_max = 0;
 
+  if (!keep_point_visible)
+    goto out;
+
  too_near_end:
 
   /* Decide whether to scroll down.  */
@@ -18004,6 +18009,8 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
   /* Run window scroll functions.  */
   startp = run_window_scroll_functions (window, startp);
 
+ out:
+
   /* Display the window.  Give up if new fonts are loaded, or if point
      doesn't appear.  */
   if (!try_window (window, startp, 0))
@@ -18183,6 +18190,10 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
     return rc;
 #endif
 
+  /* TODO: enable this optimization.  */
+  if (!keep_point_visible)
+    return CURSOR_MOVEMENT_CANNOT_BE_USED;
+
   /* Previously, there was a check for Lisp integer in the
      if-statement below. Now, this field is converted to
      ptrdiff_t, thus zero means invalid position in a buffer.  */
@@ -18770,6 +18781,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       clear_glyph_matrix (w->desired_matrix);
     }
 
+  debug_method_add (w, "real redisplay starts");
+
   /* Otherwise set up data on this window; select its buffer and point
      value.  */
   /* Really select the buffer, for the sake of buffer-local
@@ -18992,6 +19005,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	    new_vpos = MATRIX_ROW_BOTTOM_Y (r);
 	  else	/* Give up and just move to the middle of the window.  */
 	    new_vpos = window_box_height (w) / 2;
+
 	}
 
       if (!cursor_row_fully_visible_p (w, false, false, false))
@@ -19223,10 +19237,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	  IF_DEBUG (debug_method_add (w, "1"));
 	  clear_glyph_matrix (w->desired_matrix);
 	  if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
-	    /* -1 means we need to scroll.
-	       0 means we need new matrices, but fonts_changed
-	       is set in that case, so we will detect it below.  */
-	    goto try_to_scroll;
+	    {
+	      /* -1 means we need to scroll.
+		 0 means we need new matrices, but fonts_changed
+		 is set in that case, so we will detect it below.  */
+	      goto try_to_scroll;
+	    }
 	}
 
       if (f->fonts_changed)
@@ -19255,7 +19271,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
  try_to_scroll:
 
-  /* Redisplay the mode line.  Select the buffer properly for that.  */
+ /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
       update_mode_line = true;
@@ -19301,6 +19317,9 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	}
     }
 
+  if (!keep_point_visible && PT == w->last_point)
+    goto maybe_try_window;
+
   /* Finally, just choose a place to start which positions point
      according to user preferences.  */
 
@@ -19317,6 +19336,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Determine the window start relative to point.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
+
   if (centering_position < 0)
     {
       ptrdiff_t margin_pos = CHARPOS (startp);
@@ -19584,6 +19604,53 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       centering_position = 0;
       goto recenter;
     }
+  goto done;
+
+ maybe_try_window:
+
+  /* Set the window start position here explicitly if it is outside
+     the accessible portion of the buffer.  */
+
+  if (CHARPOS (startp) < BEGV
+      || CHARPOS (startp) > ZV)
+    {
+      if (CHARPOS (startp) < BEGV)
+	set_marker_both (w->start, Qnil, BEGV, BEGV_BYTE);
+      else
+	set_marker_both (w->start, Qnil, ZV, ZV_BYTE);
+
+      SET_TEXT_POS_FROM_MARKER (startp, w->start);
+
+      /* Run scroll hooks.  */
+      startp = run_window_scroll_functions (window, startp);
+    }
+
+  /* We invoke try_window and try_window_reusing_current_matrix below,
+     and they manipulate the bidi cache.  Save and restore the cache
+     state of our iterator, so we could continue using it after that.  */
+  itdata = bidi_shelve_cache ();
+
+  /* Redisplay the window.  */
+  use_desired_matrix = false;
+  if (!current_matrix_up_to_date_p
+      || windows_or_buffers_changed
+      || f->cursor_type_changed
+      /* Don't use try_window_reusing_current_matrix in this case
+	 because it can have changed the buffer.  */
+      || !NILP (Vwindow_scroll_functions)
+      || !just_this_one_p
+      || MINI_WINDOW_P (w)
+      || !(used_current_matrix_p
+	   = try_window_reusing_current_matrix (w)))
+    use_desired_matrix = (try_window (window, startp, 0) == 1);
+
+  bidi_unshelve_cache (itdata, false);
+
+  /* If new fonts have been loaded (due to fontsets), give up.  We
+     have to start a new redisplay since we need to re-adjust glyph
+     matrices.  */
+  if (f->fonts_changed)
+    goto need_larger_matrices;
 
  done:
 
@@ -19591,6 +19658,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   w->start_at_line_beg = (CHARPOS (startp) == BEGV
 			  || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
 
+  if (!keep_point_visible
+      && (w->cursor.vpos == -1)
+      && w->phys_cursor_on_p)
+    erase_phys_cursor (w);
+
   /* Display the mode line, header line, and tab-line, if we must.  */
   if ((update_mode_line
        /* If window not full width, must redo its mode line
@@ -19801,6 +19873,8 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
   struct frame *f = XFRAME (w->frame);
   int cursor_vpos = w->cursor.vpos;
 
+  debug_method_add (w, "try_window");
+
   /* Make POS the new window start.  */
   set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
 
@@ -19960,6 +20034,10 @@ try_window_reusing_current_matrix (struct window *w)
     return false;
 #endif
 
+  /* TODO: enable this optimization.  */
+  if (!keep_point_visible)
+    return false;
+
   /* The variable new_start now holds the new window start.  The old
      start `start' can be determined from the current matrix.  */
   SET_TEXT_POS_FROM_MARKER (new_start, w->start);
@@ -32389,6 +32467,9 @@ display_and_set_cursor (struct window *w, bool on,
 	      && new_cursor_width != w->phys_cursor_width)))
     erase_phys_cursor (w);
 
+  if (w->cursor.vpos == -1)
+    return;
+
   /* Don't check phys_cursor_on_p here because that flag is only set
      to false in some cases where we know that the cursor has been
      completely erased, to avoid the extra work of erasing the cursor
@@ -32749,6 +32830,9 @@ cursor_in_mouse_face_p (struct window *w)
   int vpos = w->phys_cursor.vpos;
   struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
 
+  if (vpos == -1)
+    return false;
+
   /* When the window is hscrolled, cursor hpos can legitimately be out
      of bounds, but we draw the cursor at the corresponding window
      margin in that case.  */
@@ -35493,6 +35577,10 @@ syms_of_xdisp (void)
   x_stretch_cursor_p = 0;
 #endif
 
+  DEFVAR_BOOL ("keep-point-visible", keep_point_visible,
+	       doc: /* Non-nil means to keep the point visible.  */);
+  keep_point_visible = 1;
+
   DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
     doc: /* Non-nil means highlight trailing whitespace.
 The face used for trailing whitespace is `trailing-whitespace'.  */);

[-- Attachment #3: Type: text/plain, Size: 9 bytes --]


Thanks.

  reply	other threads:[~2021-12-06  2:11 UTC|newest]

Thread overview: 111+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <87ilwd7zaq.fsf.ref@yahoo.com>
2021-11-28  3:07 ` Allowing point to be outside the window? Po Lu
2021-11-28  8:03   ` Eli Zaretskii
2021-11-28  8:13     ` Po Lu
2021-11-28  8:41       ` Eli Zaretskii
2021-11-28 12:47         ` Po Lu
2021-11-28 12:58           ` Eli Zaretskii
2021-11-28 13:10             ` Po Lu
2021-11-28 13:44               ` Eli Zaretskii
2021-11-29  1:47                 ` Po Lu
2021-11-29 13:00                   ` Eli Zaretskii
2021-11-29 13:22                     ` Po Lu
2021-11-29 13:43                       ` Eli Zaretskii
2021-11-30  1:40                         ` Po Lu
2021-11-30 16:49                           ` [External] : " Drew Adams
2021-11-30 17:26                             ` Eli Zaretskii
2021-11-30 18:10                               ` Lars Ingebrigtsen
2021-11-30 18:32                                 ` Eli Zaretskii
2021-11-30 18:49                                 ` Stefan Kangas
2021-11-30 19:21                                   ` Eli Zaretskii
2021-11-30 20:57                                     ` Drew Adams
2021-11-30 23:41                                 ` Daniel Martín
2021-12-01  8:30                                   ` martin rudalics
2021-12-01  9:10                                     ` Juri Linkov
2021-11-30 23:20                               ` Stefan Monnier
2021-12-04 11:18                           ` Po Lu
2021-12-04 12:55                             ` Eli Zaretskii
2021-12-04 13:13                               ` Po Lu
2021-12-04 16:24                                 ` Eli Zaretskii
2021-12-05  0:40                                   ` Po Lu
2021-12-04 17:15                                 ` Eli Zaretskii
2021-12-05  0:45                                   ` Po Lu
2021-12-05  9:03                                     ` Eli Zaretskii
2021-12-06  2:11                                       ` Po Lu [this message]
2021-12-06 14:13                                         ` Eli Zaretskii
2021-12-07  2:18                                           ` Po Lu
2021-12-07 13:42                                             ` Eli Zaretskii
2021-12-08  1:17                                               ` Po Lu
2021-12-08 17:14                                                 ` Eli Zaretskii
2021-12-09  0:23                                                   ` Po Lu
2021-12-09  8:02                                                     ` Eli Zaretskii
2021-12-09  9:22                                                       ` Po Lu
2021-12-09 10:02                                                         ` Eli Zaretskii
2021-12-25  6:45                                                       ` Po Lu
2021-12-25  7:07                                                         ` Eli Zaretskii
2022-02-06  7:22                                                         ` Po Lu
2022-02-06 11:34                                                           ` Eli Zaretskii
2022-02-06 11:46                                                             ` Po Lu
2022-02-06 11:55                                                               ` Eli Zaretskii
2022-02-06 12:21                                                                 ` Po Lu
2022-02-06 16:15                                                                   ` Eli Zaretskii
2022-02-07  1:21                                                                     ` Po Lu
2022-02-07  7:21                                                                       ` Po Lu
2022-02-07 13:41                                                                         ` Eli Zaretskii
2022-02-07 13:57                                                                           ` Po Lu
2022-02-07 14:24                                                                             ` Eli Zaretskii
2022-02-08  0:58                                                                               ` Po Lu
2022-02-08 17:08                                                                                 ` Eli Zaretskii
2022-02-09  1:57                                                                                   ` Po Lu
2022-02-10 13:04                                                                                     ` Eli Zaretskii
2022-02-10 13:09                                                                                       ` Po Lu
2021-12-09 11:45                                         ` Eli Zaretskii
2021-12-09 12:19                                           ` Po Lu
2021-12-09 12:45                                             ` Eli Zaretskii
2021-12-04 13:00                             ` dick
2021-12-04 13:14                               ` tomas
2021-12-04 13:19                               ` Po Lu
2021-12-04 13:41                                 ` Eli Zaretskii
2021-12-05  0:46                                   ` Po Lu
2021-12-05  7:12                                     ` Eli Zaretskii
2021-12-05  7:16                                       ` Po Lu
2021-12-05  8:48                                         ` Eli Zaretskii
2021-12-05  9:15                                           ` Po Lu
2021-12-05  9:25                                             ` Eli Zaretskii
2021-12-05  9:31                                               ` Po Lu
2021-12-05 10:34                                                 ` Eli Zaretskii
2021-12-05 10:37                                                   ` Po Lu
2021-12-04 14:17                                 ` dick
2021-12-04 16:33                                   ` Eli Zaretskii
2021-12-04 17:13                                     ` dick
2021-12-05  0:48                                       ` Po Lu
2021-11-28 14:03       ` Alan Mackenzie
2021-11-28 14:28         ` Eric S Fraga
2021-11-28 14:39           ` Eli Zaretskii
2021-11-28 16:55             ` Eric S Fraga
2021-11-28 14:42         ` dick
2021-11-28 15:39         ` Kévin Le Gouguec
2021-11-28 15:45           ` Eli Zaretskii
2021-11-28 17:14             ` Kévin Le Gouguec
2021-11-28 16:59           ` Eric S Fraga
2021-11-28 17:30             ` Kévin Le Gouguec
2021-11-29  0:34             ` Dmitry Gutov
2021-11-29  0:34         ` Po Lu
2021-12-08  1:45           ` John Ankarström
2021-12-08 12:45             ` Eli Zaretskii
2021-12-08 13:33               ` John Ankarström
2021-12-08 13:38                 ` Po Lu
2021-12-08 13:52                   ` John Ankarström
2021-12-08 14:26                 ` Eli Zaretskii
2021-12-08 16:57                   ` Stefan Monnier
2021-12-08 19:29                     ` Yuri Khan
2021-12-09  0:16                     ` Po Lu
2021-12-08 19:21                 ` Rudolf Schlatte
2021-12-08 19:56                   ` Juri Linkov
2021-12-08 20:05                     ` André A. Gomes
2021-12-08 20:31                     ` Linux console scrollback [ Was: Allowing point to be outside the window? ] Alan Mackenzie
2021-12-09  0:17                   ` Allowing point to be outside the window? Po Lu
2021-12-08 22:25                 ` Kévin Le Gouguec
2021-12-08 23:17                   ` John Ankarström
     [not found] <9603C99D-97E7-4285-A1C1-022191B6F5CC@univie.ac.at>
2021-12-08 18:43 ` Konrad Podczeck
2021-12-08 20:47   ` John Ankarström
2021-12-09 15:34 Konrad Podczeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877dcipjmk.fsf@yahoo.com \
    --to=luangruo@yahoo.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).