From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Anders Lindgren Newsgroups: gmane.emacs.bugs 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 Message-ID: References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=f46d043c7cc619efc904ef414ba2 X-Trace: ger.gmane.org 1388963651 12853 80.91.229.3 (5 Jan 2014 23:14:11 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 5 Jan 2014 23:14:11 +0000 (UTC) Cc: 16129@debbugs.gnu.org To: Stefan Monnier , Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Jan 06 00:14:18 2014 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Vzwtc-0000d0-R3 for geb-bug-gnu-emacs@m.gmane.org; Mon, 06 Jan 2014 00:14:17 +0100 Original-Received: from localhost ([::1]:59744 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vzwtc-0007Nq-Dg for geb-bug-gnu-emacs@m.gmane.org; Sun, 05 Jan 2014 18:14:16 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:48359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VzwtT-0007Nh-V8 for bug-gnu-emacs@gnu.org; Sun, 05 Jan 2014 18:14:12 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VzwtP-0003vn-2K for bug-gnu-emacs@gnu.org; Sun, 05 Jan 2014 18:14:07 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:51331) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VzwtO-0003vb-VG for bug-gnu-emacs@gnu.org; Sun, 05 Jan 2014 18:14:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1VzwtO-000488-Bo for bug-gnu-emacs@gnu.org; Sun, 05 Jan 2014 18:14:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Anders Lindgren Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 05 Jan 2014 23:14:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 16129 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 16129-submit@debbugs.gnu.org id=B16129.138896362415842 (code B ref 16129); Sun, 05 Jan 2014 23:14:01 +0000 Original-Received: (at 16129) by debbugs.gnu.org; 5 Jan 2014 23:13:44 +0000 Original-Received: from localhost ([127.0.0.1]:37117 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Vzwt4-00047P-JP for submit@debbugs.gnu.org; Sun, 05 Jan 2014 18:13:43 -0500 Original-Received: from mail-wi0-f178.google.com ([209.85.212.178]:44678) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Vzwt1-00047D-N6 for 16129@debbugs.gnu.org; Sun, 05 Jan 2014 18:13:41 -0500 Original-Received: by mail-wi0-f178.google.com with SMTP id bz8so2209210wib.5 for <16129@debbugs.gnu.org>; Sun, 05 Jan 2014 15:13:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=Dd0d6tlqb4e2nM6+E1Fcy2hG/TCFNc3pWJHnq3yazoQ=; b=a9v5gZ5/cVYDhipUAz1yQLWpnhX8ueB22K7Oh7IEL1IU5MNgUedcOgw/MGlZKa8wfl gX64xQ1XzBwao5ZKWc50u+ENYHSAac6WDbvZURxvPM7v+yr/od33bxF8QAc9Ektxkp4r jVZX/3f7+AETZi4+H+jZmxCu0bBk4uZyo5w3GNKbmNK/EiIT3J2VXVZ8gcMTwjP2OHXT dVjTSwZAtyomOGvlg7NlTrQHGf5Op04tdEKMbh7ueSWkiKx2W3AAXkRU2sFIfXqRlzcN 7fACZBGRfcHCMSKzLn9GzlqitUhJkfvEvYOr6K4XoX9UEkdckWM09CEghWSbPrajIPZ8 bffg== X-Received: by 10.180.76.103 with SMTP id j7mr9972369wiw.58.1388963618744; Sun, 05 Jan 2014 15:13:38 -0800 (PST) Original-Received: by 10.216.223.140 with HTTP; Sun, 5 Jan 2014 15:13:38 -0800 (PST) In-Reply-To: X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:83033 Archived-At: --f46d043c7cc619efc904ef414ba2 Content-Type: text/plain; charset=ISO-8859-1 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 >>>> >>> >>> >> > --f46d043c7cc619efc904ef414ba2 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Hi again!

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

When "redisplay_window" is called, it goes in= to the case where "try_cursor_movement" is called.

=
Inside this routine, the row is picked up. The row (when using t= he 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 th= e last redisplay.

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

The routine fir= st declare this to be a "success" (in the neither forward nor bac= kward case). Later in the function it comes to the following statement:

=A0if (PT < MATRIX_ROW_START_CHARPOS (row)
=A0 =A0 =A0|| PT > MATRIX_ROW_END_CHA= RPOS (row))

This fails, making the function return "=A0C= URSOR_MOVEMENT_MUST_SCROLL", which is turn cause "redisplay_windo= w" to recenter the window.

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

Sincerely,
=A0 =A0 Anders Lindgren
=


On Thu, Jan 2, 2014 at 7:39 PM, Anders Lindgren <andlind@gmail.com&= gt; 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 recente= ring code in the display engine that have gone "crazy".

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

To reproduce, do the following:

=A0 =A0 emacs -Q
=A0 =A0 Enter and evaluate the following:

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

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

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

Here, the windo= w will be recentered without there being any reason for it.

Note that this will apply to any window in any frame, a= s long as there is a window where window-start =3D=3D point-max, even if th= e 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,
=A0 =A0 =A0Anders Lindgren



On Thu, Jan 2, 2014 at 2:55 P= M, Anders Lindgren <andlind@gmail.com> 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 ind= icates that some primitive display-related function returns incorrect value= s.

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

You can verify this by doi= ng the following steps:

=A0 =A0 emacs -Q
=A0 =A0 C-h t
=A0 = =A0 M->
=A0 =A0 M-x follow-delete-other-windows-and-split RET<= /div>
=A0 =A0 C-p
=A0 =A0 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 w= indow, which probably is due to incorrect values being reported from primit= ive functions. (For example, in bug #15957 `window-end' didn't hono= ur it's FORCE argument, since some display functions didn't mark th= e 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 cl= ose 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,
=A0 =A0 Anders Lindgren
=


On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren <<= a href=3D"mailto:andlind@gmail.com" target=3D"_blank">andlind@gmail.com= > wrote:
Hi!

I ag= ree 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 hel= p you track down the problems with the slowdown.)

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

=A0 =A0 =A0emacs -Q
=A0 =A0 =A0C-x 3
=A0 =A0 =A0C-x o
=A0 =A0 =A0M-: (set-window-start (selected-win= dow) (point-max)) RET
=A0 =A0 =A0C-x o
=A0 =A0 =A0M-<= ;
=A0 =A0 =A0blablabla =A0 =A0 (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.<= /div>

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

If you are interested in making the change in the displ= ay 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. d= on't appeal to me at all.

=A0 =A0 -- Anders



On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier <<= a href=3D"mailto:monnier@iro.umontreal.ca" target=3D"_blank">monnier@iro.um= ontreal.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 win= dow,
> follow-mode tries to display this window without any content (by setti= ng
> the window start to point-max). Unfortunately, the Emacs display engin= e
> 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. =A0Maybe a good way is =A0 =A0to do the following: put window-point at point-max, and add an overl= ay
=A0 =A0on window-start...point-max that makes the text invisible (with
=A0 =A0a `window' property, so it's only invisible in that window).=
=A0 =A0Of course, maybe that won't work either. =A0But hooking everywhe= re
=A0 =A0doesn't sound like a good idea.


-- Stefab




--f46d043c7cc619efc904ef414ba2--