unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Scrolling and follow-mode
@ 2014-04-21 16:17 Alan Mackenzie
  2014-04-22 20:20 ` Anders Lindgren
  0 siblings, 1 reply; 3+ messages in thread
From: Alan Mackenzie @ 2014-04-21 16:17 UTC (permalink / raw)
  To: Anders Lindgren, emacs-devel

Hi, Anders, hi, Emacs.

With follow-mode enabled, the functions follow-scroll-up and
follow-scroll-down don't work very well when given a numerical argument.

In follow-scroll-up, the flag follow-internal-force-redisplay gets set,
which causes the post-command-hook function (a) to bypass the code which
selects the window to put point in; (b) to force redisplay to rescroll
the current window.  Both of these are undesirable when point is near a
boundary of one window, and should pass into the adjacent window on the
scrolling.

I have fixed this by causing the two scrolling functions to set a flag
which causes follow-adjust-window to align its windows as its first
action, then allowing it to select the appropriate window for point with
the existing code.  There are one or two minor changes too.

Comments on this fix are welcome.  Here is the patch (based on the
recent trunk revision 116992.




*** emacs/emacs.bzr/trunk/lisp/follow.el	2014-02-15 19:53:57.000000000 +0000
--- follow.el	2014-04-21 16:15:28.000000000 +0000
***************
*** 347,352 ****
--- 347,355 ----
  (defvar follow-windows-start-end-cache nil
    "Cache used by `follow-window-start-end'.")
  
+ (defvar follow-fixed-window nil
+   "When non-nil, the window which must not be scrolled.
+ This is typically set by explicit scrolling commands.")
  ;;; Debug messages
  
  ;; This inline function must be as small as possible!
***************
*** 439,444 ****
--- 442,496 ----
  
  ;;; Scroll
  
+ (defun follow-get-scrolled-point (dest windows)
+   "Calculate the correct value for point after a scrolling operation.
+ 
+ DEST is our default position, typically where point was before the scroll.
+ If `scroll-preserve-screen-position' is non-nil and active, DEST will be
+ in the same screen position as before the scroll.  WINDOWS is the list of
+ windows in the follow chain.
+ 
+ This function attempts to duplicate the point placing from
+ `window_scroll_line_based' in the Emacs core source window.c.
+ 
+ Return the new position."
+   (if (and scroll-preserve-screen-position
+ 	   (get this-command 'scroll-command))
+       dest
+     (let ((dest-column
+ 	   (save-excursion
+ 	     (goto-char dest)
+ 	     (- (current-column)
+ 		(progn (vertical-motion 0) (current-column)))))
+ 	  (limit0
+ 	   (with-selected-window (car windows)
+ 	     (save-excursion
+ 	       (goto-char (window-start))
+ 	       (vertical-motion 0)
+ 	       (point))))
+ 	  (limitn
+ 	   (with-selected-window (car (reverse windows))
+ 	     (save-excursion
+ 	       (goto-char (window-end nil t))
+ 	       (if (pos-visible-in-window-p)
+ 		   (point)		; i.e. (point-max)
+ 		 (1- (point)))))))
+       (follow-debug-message "dest: %s; dest-column: %s; limitn: %s" dest dest-column limitn)
+       (cond
+        ((< dest limit0)
+ 	(with-selected-window (car windows)
+ 	  (save-excursion
+ 	    (goto-char limit0)
+ 	    (vertical-motion (cons dest-column 0))
+ 	    (point))))
+        ((> dest limitn)
+ 	(with-selected-window (car (reverse windows))
+ 	  (save-excursion
+ 	    (goto-char limitn)
+ 	    (vertical-motion (cons dest-column 0))
+ 	    (point))))
+        (t dest)))))
+ 
  ;; `scroll-up' and `-down', but for windows in Follow mode.
  ;;
  ;; Almost like the real thing, except when the cursor ends up outside
***************
*** 454,459 ****
--- 506,512 ----
  ;; position...  (This would also be corrected if we would have had a
  ;; good redisplay abstraction.)
  
+ ;;;###autoload
  (defun follow-scroll-up (&optional arg)
    "Scroll text in a Follow mode window chain up.
  
***************
*** 467,475 ****
    (interactive "P")
    (cond ((not follow-mode)
  	 (scroll-up arg))
  	(arg
! 	 (save-excursion (scroll-up arg))
! 	 (setq follow-internal-force-redisplay t))
  	(t
  	 (let* ((windows (follow-all-followers))
  		(end (window-end (car (reverse windows)))))
--- 520,534 ----
    (interactive "P")
    (cond ((not follow-mode)
  	 (scroll-up arg))
+ 	((eq arg '-)
+ 	 (follow-scroll-down))
  	(arg
! 	 (let ((opoint (point)))
! 	   (scroll-up arg)
! 	   (unless (and scroll-preserve-screen-position
! 			(get this-command 'scroll-command))
! 	     (goto-char opoint))
! 	   (setq follow-fixed-window (selected-window))))
  	(t
  	 (let* ((windows (follow-all-followers))
  		(end (window-end (car (reverse windows)))))
***************
*** 481,488 ****
  		 (goto-char end))
  	     (vertical-motion (- next-screen-context-lines))
  	     (set-window-start (car windows) (point)))))))
  
! 
  (defun follow-scroll-down (&optional arg)
    "Scroll text in a Follow mode window chain down.
  
--- 540,548 ----
  		 (goto-char end))
  	     (vertical-motion (- next-screen-context-lines))
  	     (set-window-start (car windows) (point)))))))
+ (put 'follow-scroll-up 'scroll-command t)
  
! ;;;###autoload
  (defun follow-scroll-down (&optional arg)
    "Scroll text in a Follow mode window chain down.
  
***************
*** 492,503 ****
  If called with an argument, scroll ARG lines down.
  Negative ARG means scroll upward.
  
! Works like `scroll-up' when not in Follow mode."
    (interactive "P")
    (cond ((not follow-mode)
! 	 (scroll-up arg))
  	(arg
! 	 (save-excursion (scroll-down arg)))
  	(t
  	 (let* ((windows (follow-all-followers))
  		(win (car (reverse windows)))
--- 552,571 ----
  If called with an argument, scroll ARG lines down.
  Negative ARG means scroll upward.
  
! Works like `scroll-down' when not in Follow mode."
    (interactive "P")
    (cond ((not follow-mode)
! 	 (scroll-down arg))
! 	((eq arg '-)
! 	 (follow-scroll-up))
  	(arg
! 	 (let ((opoint (point)))
! 	   (scroll-down arg)
! 	   (unless (and scroll-preserve-screen-position
! 			(get this-command 'scroll-command))
! 	     (goto-char opoint))
! 	   (setq follow-fixed-window (selected-window)))
! 	 )
  	(t
  	 (let* ((windows (follow-all-followers))
  		(win (car (reverse windows)))
***************
*** 513,518 ****
--- 581,587 ----
  	     (goto-char start)
  	     (vertical-motion (- next-screen-context-lines 1))
  	     (setq follow-internal-force-redisplay t))))))
+ (put 'follow-scroll-down 'scroll-command t)
  
  (declare-function comint-adjust-point "comint" (window))
  (defvar comint-scroll-show-maximum-output)
***************
*** 1132,1143 ****
               (not (window-minibuffer-p win)))
      (let* ((dest (point))
             (windows (follow-all-followers win))
!            (win-start-end (progn
!                             (follow-update-window-start (car windows))
!                             (follow-windows-start-end windows)))
!            (aligned (follow-windows-aligned-p win-start-end))
!            (visible (follow-pos-visible dest win win-start-end))
             selected-window-up-to-date)
        (unless (and aligned visible)
          (setq follow-windows-start-end-cache nil))
  
--- 1201,1222 ----
               (not (window-minibuffer-p win)))
      (let* ((dest (point))
             (windows (follow-all-followers win))
!            win-start-end aligned visible 
             selected-window-up-to-date)
+ 
+       ;; If we've explicitly scrolled, align the windows first.
+       (when follow-fixed-window
+ 	(follow-debug-message "fixed")
+ 	(follow-redisplay windows win)
+ 	(setq dest (follow-get-scrolled-point dest windows))
+ 	(goto-char dest)
+ 	(setq follow-fixed-window nil))
+       (setq
+        win-start-end (progn
+ 		       (follow-update-window-start (car windows))
+ 		       (follow-windows-start-end windows))
+        aligned (follow-windows-aligned-p win-start-end)
+        visible (follow-pos-visible dest win win-start-end))
        (unless (and aligned visible)
          (setq follow-windows-start-end-cache nil))
  
***************
*** 1184,1190 ****
             ;; It should be optimized for speed.
             ((and visible aligned)
              (follow-debug-message "same"))
!            ;; Pick a position in any window.  If the display is ok,
             ;; this picks the `correct' window.
             ((follow-select-if-visible dest win-start-end)
              (follow-debug-message "visible")
--- 1263,1269 ----
             ;; It should be optimized for speed.
             ((and visible aligned)
              (follow-debug-message "same"))
! 	   ;; Pick a position in any window.  If the display is ok,
             ;; this picks the `correct' window.
             ((follow-select-if-visible dest win-start-end)
              (follow-debug-message "visible")



-- 
Alan Mackenzie (Nuremberg, Germany).
`



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Scrolling and follow-mode
  2014-04-21 16:17 Scrolling and follow-mode Alan Mackenzie
@ 2014-04-22 20:20 ` Anders Lindgren
  2014-04-27 11:52   ` Alan Mackenzie
  0 siblings, 1 reply; 3+ messages in thread
From: Anders Lindgren @ 2014-04-22 20:20 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

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

Hi Alan and Emacs!

Scrolling a few lines at a time was obviously something that I do very
seldom -- it appears that I missed that case when I wrote follow-mode, and
I have never seen this problem for the (almost) twenty years I've been
using it. Thanks for finding and fixing the problem!

When it comes to the patch, it looks well written. I have only two comments:

* The documentation says that `follow-fixed-window` is the window that must
not be scrolled. However, in the code, it's only read once, as the
condition to a `when`, so the actual value doesn't matter as long as it's
non-nil. Wouldn't it better do document is a boolean?

* The code at (your) lines --- 1201,1222 ---- could be cleaner. It contains
a `let*` that sets two variables, `dest` and `windows` and set a bunch
others to a default nil value. The others are later set using a `setq`. I
would suggest placing your code before the first assignment of `dest` and
simply move the point, that way `dest` will get the value of the new point.
Then use a new `let*` to set the others. Like the following (untested) code:

(let ((windows (follow-all-followers win)))
  (when follow-fixed-window
    (follow-debug-message "fixed")
    (follow-redisplay windows win)
    (goto-char (follow-get-scrolled-point (point) windows))
    (setq follow-fixed-window nil))
  (let* ((dest (point))
         (win-start-end (progn
                          (follow-update-window-start (car windows))
                          (follow-windows-start-end windows)))
         (aligned (follow-windows-aligned-p win-start-end))
         (visible (follow-pos-visible dest win win-start-end))
         selected-window-up-to-date)
    (unless (and aligned visible)
      (setq follow-windows-start-end-cache nil))


Again, thanks!

Sincerely,
    Anders Lindgren



On Mon, Apr 21, 2014 at 6:17 PM, Alan Mackenzie <acm@muc.de> wrote:

> Hi, Anders, hi, Emacs.
>
> With follow-mode enabled, the functions follow-scroll-up and
> follow-scroll-down don't work very well when given a numerical argument.
>
> In follow-scroll-up, the flag follow-internal-force-redisplay gets set,
> which causes the post-command-hook function (a) to bypass the code which
> selects the window to put point in; (b) to force redisplay to rescroll
> the current window.  Both of these are undesirable when point is near a
> boundary of one window, and should pass into the adjacent window on the
> scrolling.
>
> I have fixed this by causing the two scrolling functions to set a flag
> which causes follow-adjust-window to align its windows as its first
> action, then allowing it to select the appropriate window for point with
> the existing code.  There are one or two minor changes too.
>
> Comments on this fix are welcome.  Here is the patch (based on the
> recent trunk revision 116992.
>
>
>
>
> *** emacs/emacs.bzr/trunk/lisp/follow.el        2014-02-15
> 19:53:57.000000000 +0000
> --- follow.el   2014-04-21 16:15:28.000000000 +0000
> ***************
> *** 347,352 ****
> --- 347,355 ----
>   (defvar follow-windows-start-end-cache nil
>     "Cache used by `follow-window-start-end'.")
>
> + (defvar follow-fixed-window nil
> +   "When non-nil, the window which must not be scrolled.
> + This is typically set by explicit scrolling commands.")
>   ;;; Debug messages
>
>   ;; This inline function must be as small as possible!
> ***************
> *** 439,444 ****
> --- 442,496 ----
>
>   ;;; Scroll
>
> + (defun follow-get-scrolled-point (dest windows)
> +   "Calculate the correct value for point after a scrolling operation.
> +
> + DEST is our default position, typically where point was before the
> scroll.
> + If `scroll-preserve-screen-position' is non-nil and active, DEST will be
> + in the same screen position as before the scroll.  WINDOWS is the list of
> + windows in the follow chain.
> +
> + This function attempts to duplicate the point placing from
> + `window_scroll_line_based' in the Emacs core source window.c.
> +
> + Return the new position."
> +   (if (and scroll-preserve-screen-position
> +          (get this-command 'scroll-command))
> +       dest
> +     (let ((dest-column
> +          (save-excursion
> +            (goto-char dest)
> +            (- (current-column)
> +               (progn (vertical-motion 0) (current-column)))))
> +         (limit0
> +          (with-selected-window (car windows)
> +            (save-excursion
> +              (goto-char (window-start))
> +              (vertical-motion 0)
> +              (point))))
> +         (limitn
> +          (with-selected-window (car (reverse windows))
> +            (save-excursion
> +              (goto-char (window-end nil t))
> +              (if (pos-visible-in-window-p)
> +                  (point)              ; i.e. (point-max)
> +                (1- (point)))))))
> +       (follow-debug-message "dest: %s; dest-column: %s; limitn: %s" dest
> dest-column limitn)
> +       (cond
> +        ((< dest limit0)
> +       (with-selected-window (car windows)
> +         (save-excursion
> +           (goto-char limit0)
> +           (vertical-motion (cons dest-column 0))
> +           (point))))
> +        ((> dest limitn)
> +       (with-selected-window (car (reverse windows))
> +         (save-excursion
> +           (goto-char limitn)
> +           (vertical-motion (cons dest-column 0))
> +           (point))))
> +        (t dest)))))
> +
>   ;; `scroll-up' and `-down', but for windows in Follow mode.
>   ;;
>   ;; Almost like the real thing, except when the cursor ends up outside
> ***************
> *** 454,459 ****
> --- 506,512 ----
>   ;; position...  (This would also be corrected if we would have had a
>   ;; good redisplay abstraction.)
>
> + ;;;###autoload
>   (defun follow-scroll-up (&optional arg)
>     "Scroll text in a Follow mode window chain up.
>
> ***************
> *** 467,475 ****
>     (interactive "P")
>     (cond ((not follow-mode)
>          (scroll-up arg))
>         (arg
> !        (save-excursion (scroll-up arg))
> !        (setq follow-internal-force-redisplay t))
>         (t
>          (let* ((windows (follow-all-followers))
>                 (end (window-end (car (reverse windows)))))
> --- 520,534 ----
>     (interactive "P")
>     (cond ((not follow-mode)
>          (scroll-up arg))
> +       ((eq arg '-)
> +        (follow-scroll-down))
>         (arg
> !        (let ((opoint (point)))
> !          (scroll-up arg)
> !          (unless (and scroll-preserve-screen-position
> !                       (get this-command 'scroll-command))
> !            (goto-char opoint))
> !          (setq follow-fixed-window (selected-window))))
>         (t
>          (let* ((windows (follow-all-followers))
>                 (end (window-end (car (reverse windows)))))
> ***************
> *** 481,488 ****
>                  (goto-char end))
>              (vertical-motion (- next-screen-context-lines))
>              (set-window-start (car windows) (point)))))))
>
> !
>   (defun follow-scroll-down (&optional arg)
>     "Scroll text in a Follow mode window chain down.
>
> --- 540,548 ----
>                  (goto-char end))
>              (vertical-motion (- next-screen-context-lines))
>              (set-window-start (car windows) (point)))))))
> + (put 'follow-scroll-up 'scroll-command t)
>
> ! ;;;###autoload
>   (defun follow-scroll-down (&optional arg)
>     "Scroll text in a Follow mode window chain down.
>
> ***************
> *** 492,503 ****
>   If called with an argument, scroll ARG lines down.
>   Negative ARG means scroll upward.
>
> ! Works like `scroll-up' when not in Follow mode."
>     (interactive "P")
>     (cond ((not follow-mode)
> !        (scroll-up arg))
>         (arg
> !        (save-excursion (scroll-down arg)))
>         (t
>          (let* ((windows (follow-all-followers))
>                 (win (car (reverse windows)))
> --- 552,571 ----
>   If called with an argument, scroll ARG lines down.
>   Negative ARG means scroll upward.
>
> ! Works like `scroll-down' when not in Follow mode."
>     (interactive "P")
>     (cond ((not follow-mode)
> !        (scroll-down arg))
> !       ((eq arg '-)
> !        (follow-scroll-up))
>         (arg
> !        (let ((opoint (point)))
> !          (scroll-down arg)
> !          (unless (and scroll-preserve-screen-position
> !                       (get this-command 'scroll-command))
> !            (goto-char opoint))
> !          (setq follow-fixed-window (selected-window)))
> !        )
>         (t
>          (let* ((windows (follow-all-followers))
>                 (win (car (reverse windows)))
> ***************
> *** 513,518 ****
> --- 581,587 ----
>              (goto-char start)
>              (vertical-motion (- next-screen-context-lines 1))
>              (setq follow-internal-force-redisplay t))))))
> + (put 'follow-scroll-down 'scroll-command t)
>
>   (declare-function comint-adjust-point "comint" (window))
>   (defvar comint-scroll-show-maximum-output)
> ***************
> *** 1132,1143 ****
>                (not (window-minibuffer-p win)))
>       (let* ((dest (point))
>              (windows (follow-all-followers win))
> !            (win-start-end (progn
> !                             (follow-update-window-start (car windows))
> !                             (follow-windows-start-end windows)))
> !            (aligned (follow-windows-aligned-p win-start-end))
> !            (visible (follow-pos-visible dest win win-start-end))
>              selected-window-up-to-date)
>         (unless (and aligned visible)
>           (setq follow-windows-start-end-cache nil))
>
> --- 1201,1222 ----
>                (not (window-minibuffer-p win)))
>       (let* ((dest (point))
>              (windows (follow-all-followers win))
> !            win-start-end aligned visible
>              selected-window-up-to-date)
> +
> +       ;; If we've explicitly scrolled, align the windows first.
> +       (when follow-fixed-window
> +       (follow-debug-message "fixed")
> +       (follow-redisplay windows win)
> +       (setq dest (follow-get-scrolled-point dest windows))
> +       (goto-char dest)
> +       (setq follow-fixed-window nil))
> +       (setq
> +        win-start-end (progn
> +                      (follow-update-window-start (car windows))
> +                      (follow-windows-start-end windows))
> +        aligned (follow-windows-aligned-p win-start-end)
> +        visible (follow-pos-visible dest win win-start-end))
>         (unless (and aligned visible)
>           (setq follow-windows-start-end-cache nil))
>
> ***************
> *** 1184,1190 ****
>              ;; It should be optimized for speed.
>              ((and visible aligned)
>               (follow-debug-message "same"))
> !            ;; Pick a position in any window.  If the display is ok,
>              ;; this picks the `correct' window.
>              ((follow-select-if-visible dest win-start-end)
>               (follow-debug-message "visible")
> --- 1263,1269 ----
>              ;; It should be optimized for speed.
>              ((and visible aligned)
>               (follow-debug-message "same"))
> !          ;; Pick a position in any window.  If the display is ok,
>              ;; this picks the `correct' window.
>              ((follow-select-if-visible dest win-start-end)
>               (follow-debug-message "visible")
>
>
>
> --
> Alan Mackenzie (Nuremberg, Germany).
> `
>

[-- Attachment #2: Type: text/html, Size: 14649 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Scrolling and follow-mode
  2014-04-22 20:20 ` Anders Lindgren
@ 2014-04-27 11:52   ` Alan Mackenzie
  0 siblings, 0 replies; 3+ messages in thread
From: Alan Mackenzie @ 2014-04-27 11:52 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: emacs-devel

Hi, Anders.

On Tue, Apr 22, 2014 at 10:20:46PM +0200, Anders Lindgren wrote:
> When it comes to the patch, it looks well written. I have only two comments:

> * The documentation says that `follow-fixed-window` is the window that must
> not be scrolled. However, in the code, it's only read once, as the
> condition to a `when`, so the actual value doesn't matter as long as it's
> non-nil. Wouldn't it better do document is a boolean?

Yes, I think so too.  I've changed it to a boolean.

> * The code at (your) lines --- 1201,1222 ---- could be cleaner. It contains
> a `let*` that sets two variables, `dest` and `windows` and set a bunch
> others to a default nil value. The others are later set using a `setq`. I
> would suggest placing your code before the first assignment of `dest` and
> simply move the point, that way `dest` will get the value of the new point.
> Then use a new `let*` to set the others. Like the following (untested) code:

> (let ((windows (follow-all-followers win)))
>   (when follow-fixed-window
>     (follow-debug-message "fixed")
>     (follow-redisplay windows win)
>     (goto-char (follow-get-scrolled-point (point) windows))
>     (setq follow-fixed-window nil))
>   (let* ((dest (point))
>          (win-start-end (progn
>                           (follow-update-window-start (car windows))
>                           (follow-windows-start-end windows)))
>          (aligned (follow-windows-aligned-p win-start-end))
>          (visible (follow-pos-visible dest win win-start-end))
>          selected-window-up-to-date)
>     (unless (and aligned visible)
>       (setq follow-windows-start-end-cache nil))

I've incorporated this change.  (In my own personal copy, I mean).  It is
indeed neater.

However, things aren't as simple as I thought.  In follow-scroll-up, if
point is at EOB, and at the top of the last window, (follow-scroll-up 1)
should scroll EOB into the previous window.  Instead it throws an
'end-of-buffer exception.

I've fixed this by using follow-previous-window and trying scroll-up
again.  However, the fix contains nested `condition-case's in a while
loop, and I'm not totally happy with it.  It's too "clever", really.  (I
also need to put this fix into follow-scroll-down for negative ARGs.)

Here is what the change to follow-scroll-up currently looks like:

@@ -467,9 +519,23 @@
   (interactive "P")
   (cond ((not follow-mode)
 	 (scroll-up arg))
+	((eq arg '-)
+	 (follow-scroll-down))
 	(arg
-	 (save-excursion (scroll-up arg))
-	 (setq follow-internal-force-redisplay t))
+	 (let ((opoint (point))  (owin (selected-window)))
+	   (while
+	       ;; If we are too near EOB, try scrolling the previous window.
+	       (condition-case nil (progn (scroll-up arg) nil)
+		 (end-of-buffer 
+		  (condition-case nil (progn (follow-previous-window) t)
+		    (error
+		     (select-window owin)
+		     (goto-char opoint)
+		     (signal 'end-of-buffer nil))))))
+	   (unless (and scroll-preserve-screen-position
+			(get this-command 'scroll-command))
+	     (goto-char opoint))
+	   (setq follow-fixed-window t)))
 	(t
 	 (let* ((windows (follow-all-followers))
 		(end (window-end (car (reverse windows)))))

#########################################################################

As a matter of interest, I mainly use a Linux tty for Emacs, and here
there is never a partially visible line at the bottom of the window.  I
think in a GUI environment, there almost always is.  While solving the
above issue, I stumbled over something in follow-calc-win-end: the flag
END-OF-BUFFER becomes t when EOB is at (window-end win), which is one
line beyond the end of the window (in a tty).  I think the flag is meant
to mean "EOB is fully visible in WIN"; it is commented thus somewhere
else in the file.  I've changed follow-calc-win-end as follows:

@@ -766,15 +842,16 @@
 Return (END-POS END-OF-BUFFER).
 
 Actually, the position returned is the start of the line after
-the last fully-visible line in WIN.  If WIN is nil, the selected
-window is used."
+the last fully-visible line in WIN.  END-OF-BUFFER is t when EOB
+is fully-visible in WIN.  If WIN is nil, the selected window is
+used."
   (let* ((win (or win (selected-window)))
 	 (edges (window-inside-pixel-edges win))
 	 (ht (- (nth 3 edges) (nth 1 edges)))
 	 (last-line-pos (posn-point (posn-at-x-y 0 (1- ht) win))))
     (if (pos-visible-in-window-p last-line-pos win)
 	(let ((end (window-end win t)))
-	  (list end (= end (point-max))))
+	  (list end (pos-visible-in-window-p (point-max) win)))
       (list last-line-pos nil))))
 
 (defun follow-calc-win-start (windows pos win)

.

#########################################################################

With 3 follow windows, and the last few lines of text filling the middle
window, with just EOB in the right hand window, I encountered this
problem: put point at the end of the middle window (i.e. one character
before EOB) and do C-f.  Point moves into the RH window, but the middle
and left windows scroll up 2 lines.

I tracked this down to follow-estimate-first-window-start (called from
follow-redisplay) which decrements the height of the current window
whilst moving vertically over it.  In the above case, this left point two
lines too low, causing the unwanted scrolling.

So I patched the -1 out of the function, and it works, at least on the
tty.  In the GUI, it is still scrolling 1 line up.  I'll try and track
down what's causing this.

Here is the change I've made to follow-estimate-first-window-start:

@@ -1008,7 +1085,7 @@
       (goto-char start)
       (vertical-motion 0 win)
       (dolist (w windows-before)
-	(vertical-motion (- 1 (window-text-height w)) w))
+	(vertical-motion (- (window-text-height w)) w))
       (point))))



> Again, thanks!

> Sincerely,
>     Anders Lindgren

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-04-27 11:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-21 16:17 Scrolling and follow-mode Alan Mackenzie
2014-04-22 20:20 ` Anders Lindgren
2014-04-27 11:52   ` Alan Mackenzie

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).