[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before

From: Anders Lindgren
Subject: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window
Date: Mon, 6 Jan 2014 00:13:38 +0100

Hi again!

As I haven't heard anything on this bug for a while, I tried to track down the problem myself. I have found something that looks like the cause of the problem, however, I haven't looked into a way to solve it.

When "redisplay_window" is called, it goes into the case where "try_cursor_movement" is called.

Inside this routine, the row is picked up. The row (when using the TUTORIAL example) has start and end at 46229. The point and last_point, however, are 46228, so it assumes that the point haven't moved since the last redisplay.

Clearly, "last_point" and "row" are not consistent with each other, which is assumed by try_cursor_movement (if I read it correctly).

The routine first declare this to be a "success" (in the neither forward nor backward case). Later in the function it comes to the following statement:

     || PT > MATRIX_ROW_END_CHARPOS (row))

This fails, making the function return " CURSOR_MOVEMENT_MUST_SCROLL", which is turn cause "redisplay_window" to recenter the window.

Please respond if this is enough information for you to track down the problem.

    Anders Lindgren

On Thu, Jan 2, 2014 at 7:39 PM, Anders Lindgren <address@hidden> wrote:
Hi again!

I've dug a bit more into this. It looks like it's not follow-mode that repositions the window, instead I guess it's some kind of recentering code in the display engine that have gone "crazy".

I've managed to reproduce the problem with an extremely cut-down version of the code, which simply reads and restores window-start of windows when windows-start is point-max.

To reproduce, do the following:

    emacs -Q
    Enter and evaluate the following:

(defun my-avoid-tail-recenter (&rest _rest)
  (let* ((orig-buffer (current-buffer))
(top (frame-first-window))
(win top))
    ;; If the only window in the frame is a minibuffer
    ;; window, `next-window' will never find it again...
    (unless (window-minibuffer-p top)
 (let ((start (window-start win)))
   (set-buffer (window-buffer win))
   (if (eq (point-max) start)
;; Write the same window start back, but don't
;; set the NOFORCE flag.
(set-window-start win start))
   (setq win (next-window win 'not t))
   (not (eq win top))))  ;; Loop while this is true.
      (set-buffer orig-buffer))))

(add-hook 'post-command-hook 'my-avoid-tail-recenter)

    C-x 3
    M-: (set-window-start (selected-window) (point-max)) RET
    C-x o

Here, the window will be recentered without there being any reason for it.

Note that this will apply to any window in any frame, as long as there is a window where window-start == point-max, even if the window displays a different buffer.

As this now falls outside of follow-mode, I think that I have reached the end of what I can contribute...

     Anders Lindgren

On Thu, Jan 2, 2014 at 2:55 PM, Anders Lindgren <address@hidden> wrote:
Hi again!

In addition to the problems I originally reported, I realized today that the modification also made follow-mode place windows incorrectly, which indicates that some primitive display-related function returns incorrect values.

Do you want me to report a new bug, or should we see this as a second symptom?

You can verify this by doing the following steps:

    emacs -Q
    C-h t
    M-x follow-delete-other-windows-and-split RET

After the second C-p, the left window is recentered, which is shouldn't. This typically occurs when follow-mode thinks the point is not visible in any window, which probably is due to incorrect values being reported from primitive functions. (For example, in bug #15957 `window-end' didn't honour it's FORCE argument, since some display functions didn't mark the end value as being dirty.)

I will try to track this down in more detail. However, I wanted to give you a heads up since it's appears as though you are close to a release -- it might take me a couple of days to find the problem, as I have very limited time to spend on Emacs-related things.

    Anders Lindgren

On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren <address@hidden> wrote:

I agree that we would need to find out why the patch makes Emacs slow. (In fact, I only supplied the information about the internals of follow-mode to help you track down the problems with the slowdown.)

However, I don't agree with Eli -- it is possible to place window-start at point-max! However, there is code in the display engine that explicitly recenters such windows, after a while, or when something happens. For example:

     emacs -Q
     C-x 3
     C-x o
     M-: (set-window-start (selected-window) (point-max)) RET
     C-x o
     blablabla     (type some text)

As you type text in the left window at the beginning of the scratch buffer, the right window is recentered. Follow-mode needs its windows to stay put (even the empty ones), as this is essential in creating the illusion that a number of windows make up a very tall virtual window.

When I originally wrote follow-mode (some 18 years ago), I suggested to the Emacs maintainers to add a feature to make the recentering of empty windows conditional, so that follow-mode could control this. However, at the time they were not interested so I continued with the current system, which has worked flawlessly since then.

If you are interested in making the change in the display engine, follow-mode should of course be rewritten to use it. Otherwise, I suggest that we keep it as it is today -- solutions using overlays etc. don't appeal to me at all.

    -- Anders

On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier <address@hidden> wrote:
> I am the original author of follow-mode, so I can share one interesting
> implementation detail. When the viewed buffer ends before the last window,
> follow-mode tries to display this window without any content (by setting
> the window start to point-max). Unfortunately, the Emacs display engine
> always tries ensure that windows are not empty so it repositions it... So,
> follow-mode hammers in its view of the world every chance it gets,
> currrently in post-command hook and window-scroll-functions.

Hmm.. so we have 2 things to do:
1- figure out why my patch slowed things down so much.
2- change follow-mode to use a different approach.  Maybe a good way is
   to do the following: put window-point at point-max, and add an overlay
   on window-start...point-max that makes the text invisible (with
   a `window' property, so it's only invisible in that window).
   Of course, maybe that won't work either.  But hooking everywhere
   doesn't sound like a good idea.

-- Stefab

reply via email to

[Prev in Thread] Current Thread [Next in Thread]