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: if (PT < MATRIX_ROW_START_CHARPOS (row) || 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. Sincerely, Anders Lindgren On Thu, Jan 2, 2014 at 7:39 PM, Anders Lindgren 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) > (while > (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 > C-p > > 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... > > Sincerely, > Anders Lindgren > > > > On Thu, Jan 2, 2014 at 2:55 PM, Anders Lindgren 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-> >> M-x follow-delete-other-windows-and-split RET >> C-p >> C-p >> >> 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. >> >> Sincerely, >> Anders Lindgren >> >> >> >> On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren wrote: >> >>> Hi! >>> >>> 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 >>> M-< >>> 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 < >>> monnier@iro.umontreal.ca> 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 >>>> >>> >>> >> >