Subject: bug#35860: Delayed window positioning after buffer display

From: martin rudalics <[email-masked]>
Date: Sun, 16 Jun 2019 10:16:20 +0200

> Generalized version does exactly what 'help-window-point-marker'
 > used to do, i.e.:
 >
 >    ;; `help-window-point-marker' is a marker you can move to a valid
 >    ;; position of the buffer shown in the help window in order to override
 >    ;; the standard positioning mechanism (`point-min') chosen by
 >    ;; `with-output-to-temp-buffer' and `with-temp-buffer-window'.
 >    ;; `with-help-window' has this point nowhere before exiting.  Currently
 >    ;; used by `view-lossage' to assert that the last keystrokes are always
 >    ;; visible.
 >    (defvar help-window-point-marker (make-marker)
 >      "Marker to override default `window-point' in help windows.")
 >
 > but for all windows instead of only help windows, i.e.:
 >
 >      "Marker to override default `window-point' in all windows."
 >
 > So do you think about just removing the prefix `help-' from the name:
 > `window-point-marker'?

Currently 'temp-buffer-window-show' has

       (goto-char (point-min))

and 'internal-temp-output-buffer-show' has

	  (set-window-start window (point-min) t)
	  ;; This should not be necessary.
	  (set-window-point window (point-min))

For help windows (windows showing *Help*) 'help-window-point-marker'
allows to override these assignments by a suitable assignment for that
variable.  It's hackish but still done in a pretty restricitve fashion
as follows.

First 'help-window-point-marker' is reset in 'with-help-window' via

      ;; Make `help-window-point-marker' point nowhere.  The only place
      ;; where this should be set to a buffer position is within BODY.
      (set-marker help-window-point-marker nil)

- a security guard, because that marker should be nil at that time
anyway.

Then 'help-window-point-marker' may be set by the BODY of
'with-help-window' and 'help-window-setup' will pick that up guarded
as

       (when (eq (marker-buffer help-window-point-marker) help-buffer)
	(set-window-point window help-window-point-marker)
	;; Reset `help-window-point-marker'.
	(set-marker help-window-point-marker nil))

thus (1) checking whether the marker buffer matches and (2)
immediately resetting that marker to nil.

Can you provide equivalent security guards when generalizing that
variable?  For example, you proposed

  (defun window--display-buffer (buffer window type &optional alist)
    "Display BUFFER in WINDOW.
[...]
+
+      (when window-start
+        (set-window-start window window-start)
+        (setq window-start nil))
+
+      (when window-point
+        (set-window-point window window-point)
+        (setq window-point nil))

What happens with these markers when 'display-buffer-no-window' gets
called?  Or some user provided routine provokes an unhandled error?
You don't even check the marker buffer of these variables so some old,
completely unrelated marker could get reused here.

The *Help* buffer is special because it's used in a centralized way
for any help Emacs provides (that's also why it has a browsable
history).  Buffers displayed by 'display-buffer' OTOH don't obey any
such restricitions.  They don't even have a BODY as the only place
where markers as the ones you propose can be set.

Also 'temp-buffer-window-show' and 'internal-temp-output-buffer-show'
are special because they explicitly wants to set window point to BOB.
So there's some predefined mechanism we (1) are aware of and (2) want
to override deliberately.

So we'd carefully have to examine first how the mechanism you propose
could be abused, how to handle any errors in using and failing to
reset these markers and last but not least tell why we don't provide
'window-point' and 'window-start' action alist entries instead of such
global variables.

martin