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

From: Juri Linkov <[email-masked]>
Date: Tue, 11 Jun 2019 23:53:00 +0300

>> 0. emacs -Q
>> 1. C-h l
>>
>> Then point in the *Help* buffer should be at the bottom,
>> but when setting switch-to-buffer-preserve-window-point to nil
>> instead of using set-marker, point still is at the top of the buffer.
>
> I'm confused.  Here point in the *Help* buffer is always at bottom
> regardless of how 'switch-to-buffer-preserve-window-point' is set.

Dmitry reverted my patch in bug#35624 because of no progress here,
so I needed to implement this quickly.  It generalizes
help-window-point-marker to a more general variable useful
not only in the Help buffer but everywhere, and all my tests show
that it works well:

diff --git a/lisp/help.el b/lisp/help.el
index 42ff375565..c046fe6a49 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -37,15 +37,7 @@
 (add-hook 'temp-buffer-setup-hook 'help-mode-setup)
 (add-hook 'temp-buffer-show-hook 'help-mode-finish)
 
-;; `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.")
+(defvaralias 'help-window-point-marker 'window-point)
 
 (defvar help-window-old-frame nil
   "Frame selected at the time `with-help-window' is invoked.")
@@ -481,7 +473,8 @@ view-lossage
           (comment-indent)
 	  (forward-line 1)))
       ;; Show point near the end of "lossage", as we did in Emacs 24.
-      (set-marker help-window-point-marker (point)))))
+      (setq window-point (point))
+      (setq window-start (save-excursion (forward-line (- 5 (window-height))) (point))))))
 
 
 ;; Key bindings
@@ -1249,12 +1242,6 @@ help-window-setup
 	 (frame (window-frame window)))
 
     (when help-buffer
-      ;; Handle `help-window-point-marker'.
-      (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))
-
       ;; If the help window appears on another frame, select it if
       ;; `help-window-select' is non-nil and give that frame input focus
       ;; too.  See also Bug#19012.
@@ -1327,7 +1314,7 @@ help-window-setup
 ;; (3) An option (customizable via `help-window-select') to select the
 ;;     help window automatically.
 
-;; (4) A marker (`help-window-point-marker') to move point in the help
+;; (4) A marker (`window-point') to move point in the help
 ;;     window to an arbitrary buffer position.
 (defmacro with-help-window (buffer-or-name &rest body)
   "Evaluate BODY, send output to BUFFER-OR-NAME and show in a help window.
@@ -1339,9 +1326,9 @@ with-help-window
 Most of this is done by `help-window-setup', which see."
   (declare (indent 1) (debug t))
   `(progn
-     ;; Make `help-window-point-marker' point nowhere.  The only place
+     ;; Make `window-point' point nowhere.  The only place
      ;; where this should be set to a buffer position is within BODY.
-     (set-marker help-window-point-marker nil)
+     (when window-point (setq window-point nil))
      (let ((temp-buffer-window-setup-hook
 	    (cons 'help-mode-setup temp-buffer-window-setup-hook))
 	   (temp-buffer-window-show-hook
diff --git a/lisp/window.el b/lisp/window.el
index 69b1299dbd..e2796cecba 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -6795,6 +6795,22 @@ window--even-window-sizes
            (/ (- (window-total-height window) (window-total-height)) 2))
         (error nil))))))
 
+(defvar window-point nil
+  "Marker to override default `window-point' in help windows.
+`window-point' is a buffer-local marker you can move to a valid position of
+the buffer shown in the window in order to override the standard
+positioning mechanism (`point-min') chosen by window displaying functions.")
+(make-variable-buffer-local 'window-point)
+(put 'window-point 'permanent-local t)
+
+(defvar window-start nil
+  "Marker to override default `window-start' in help windows.
+`window-start' is a buffer-local marker you can move to a valid position of
+the buffer shown in the window in order to override the standard
+positioning mechanism (`point-min') chosen by window displaying functions.")
+(make-variable-buffer-local 'window-start)
+(put 'window-start 'permanent-local t)
+
 (defun window--display-buffer (buffer window type &optional alist)
   "Display BUFFER in WINDOW.
 WINDOW must be a live window chosen by a buffer display action
@@ -6913,6 +6929,15 @@ window--display-buffer
 	(when (consp preserve-size)
 	  (window-preserve-size window t (car preserve-size))
 	  (window-preserve-size window nil (cdr preserve-size)))))
+
+      (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))
+
       ;; Assign any window parameters specified.
       (let ((parameters (cdr (assq 'window-parameters alist))))
         (dolist (parameter parameters)
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 61c13026cc..20a67dd6a7 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1017,9 +1017,11 @@ vc-git-print-log
     ;; If the buffer exists from a previous invocation it might be
     ;; read-only.
     (let ((inhibit-read-only t))
-      (with-current-buffer
-          buffer
-	(apply 'vc-git-command buffer
+      (with-current-buffer buffer
+	(insert (propertize "(Press 'd' here to see the diff against the current working revision)\n"
+                            'font-lock-face 'shadow))
+        (setq window-start (point))
+        (apply 'vc-git-command buffer
 	       'async files
 	       (append
 		'("log" "--no-color")