From fd8eaa72a611d050e1fe9c38c466c7812c7795dd Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 9 May 2022 09:37:58 +0800 Subject: [PATCH] Allow precision-scrolling nonselected windows when the minibuffer is resized * doc/lispref/windows.texi (Vertical Scrolling): Document new `preserve-vscroll-p' parameter of `set-window-vscroll'. * etc/NEWS: Announce new parameter. * lisp/pixel-scroll.el (pixel-scroll-precision-scroll-down-page) (pixel-scroll-precision-scroll-up-page): Use that parameter when setting the vscroll. * src/window.c (window_scroll_pixel_based, Fset_window_vscroll): Adjust for new parameter. * src/window.h (struct window): New flag `preserve_vscroll_p'. * src/xdisp.c (redisplay_window): Preserve the vscroll inside force_start on frozen windows with that flag set. (bug#55312) --- doc/lispref/windows.texi | 8 +++++++- etc/NEWS | 5 +++++ lisp/pixel-scroll.el | 6 +++--- src/window.c | 23 ++++++++++++++++------- src/window.h | 4 ++++ src/xdisp.c | 9 ++++++++- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 97908bea001..57763c146da 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -5508,7 +5508,7 @@ pixels, rather than in units of the normal line height. @end example @end defun -@defun set-window-vscroll window lines &optional pixels-p +@defun set-window-vscroll window lines &optional pixels-p preserve-vscroll-p This function sets @var{window}'s vertical scroll position to @var{lines}. If @var{window} is @code{nil}, the selected window is used. The argument @var{lines} should be zero or positive; if not, it @@ -5530,6 +5530,12 @@ The return value is the result of this rounding. If @var{pixels-p} is non-@code{nil}, @var{lines} specifies a number of pixels. In this case, the return value is @var{lines}. + +Normally, the vscroll does not take effect on windows that aren't the +@code{minibuffer-scroll-window} or the selected window when the +mini-window is resized (@pxref{Minibuffer Windows}). This ``frozen'' +behavior is disabled when the @var{preserve-vscroll-p} parameter is +non-@code{nil}, which means to set the vscroll as usual. @end defun @defvar auto-window-vscroll diff --git a/etc/NEWS b/etc/NEWS index dbdc161a416..5860010f022 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2100,6 +2100,11 @@ dimensions. Specifying a cons as the FROM argument allows to start measuring text from a specified amount of pixels above or below a position. ++++ +** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P. +This means the vscroll will not be reset when set on a window that is +"frozen" due to a mini-window being resized. + ** XDG support --- diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el index b0fe2f56c03..fc7e680c262 100644 --- a/lisp/pixel-scroll.el +++ b/lisp/pixel-scroll.el @@ -547,7 +547,7 @@ the height of the current window." (beginning-of-visual-line) (point))) t) - (set-window-vscroll nil desired-vscroll t))) + (set-window-vscroll nil desired-vscroll t t))) (defun pixel-scroll-precision-scroll-down (delta) "Scroll the current window down by DELTA pixels." @@ -586,7 +586,7 @@ the height of the current window." (goto-char up-point))) (let ((current-vscroll (window-vscroll nil t))) (setq delta (- delta current-vscroll)) - (set-window-vscroll nil 0 t) + (set-window-vscroll nil 0 t t) (when (> delta 0) (let* ((start (window-start)) (dims (window-text-pixel-size nil (cons start (- delta)) @@ -602,7 +602,7 @@ the height of the current window." (signal 'beginning-of-buffer nil)) (setq delta (- delta height)))) (when (< delta 0) - (set-window-vscroll nil (- delta) t))))) + (set-window-vscroll nil (- delta) t t))))) (defun pixel-scroll-precision-interpolate (delta &optional old-window) "Interpolate a scroll of DELTA pixels. diff --git a/src/window.c b/src/window.c index 72d10f9da23..47c008a643a 100644 --- a/src/window.c +++ b/src/window.c @@ -5636,7 +5636,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) if (w->vscroll < 0 && rtop > 0) { px = max (0, -w->vscroll - min (rtop, -dy)); - Fset_window_vscroll (window, make_fixnum (px), Qt); + Fset_window_vscroll (window, make_fixnum (px), Qt, + Qnil); return; } } @@ -5646,7 +5647,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) if (rbot > 0 && (w->vscroll < 0 || vpos == 0)) { px = max (0, -w->vscroll + min (rbot, dy)); - Fset_window_vscroll (window, make_fixnum (px), Qt); + Fset_window_vscroll (window, make_fixnum (px), Qt, + Qnil); return; } @@ -5655,7 +5657,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) { ptrdiff_t spos; - Fset_window_vscroll (window, make_fixnum (0), Qt); + Fset_window_vscroll (window, make_fixnum (0), Qt, + Qnil); /* If there are other text lines above the current row, move window start to current row. Else to next row. */ if (rbot > 0) @@ -5674,7 +5677,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) } } /* Cancel previous vscroll. */ - Fset_window_vscroll (window, make_fixnum (0), Qt); + Fset_window_vscroll (window, make_fixnum (0), Qt, Qnil); } itdata = bidi_shelve_cache (); @@ -7944,7 +7947,7 @@ optional second arg PIXELS-P means value is measured in pixels. */) DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll, - 2, 3, 0, + 2, 4, 0, doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL. This takes effect when displaying tall lines or images. @@ -7954,8 +7957,12 @@ optional third arg PIXELS-P non-nil means that VSCROLL is in pixels. If PIXELS-P is nil, VSCROLL may have to be rounded so that it corresponds to an integral number of pixels. The return value is the result of this rounding. -If PIXELS-P is non-nil, the return value is VSCROLL. */) - (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p) +If PIXELS-P is non-nil, the return value is VSCROLL. + +PRESERVE_VSCROLL_P makes setting the start of WINDOW preserve the +vscroll if its start is "frozen" due to a resized mini-window. */) + (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p, + Lisp_Object preserve_vscroll_p) { struct window *w = decode_live_window (window); struct frame *f = XFRAME (w->frame); @@ -7984,6 +7991,8 @@ If PIXELS-P is non-nil, the return value is VSCROLL. */) /* Mark W for redisplay. (bug#55299) */ wset_redisplay (w); } + + w->preserve_vscroll_p = !NILP (preserve_vscroll_p); } return Fwindow_vscroll (window, pixels_p); diff --git a/src/window.h b/src/window.h index 387a3be36a9..7f7de588463 100644 --- a/src/window.h +++ b/src/window.h @@ -445,6 +445,10 @@ struct window window. */ bool_bf suspend_auto_hscroll : 1; + /* True if vscroll should be preserved while forcing the start due + to a frozen window. */ + bool_bf preserve_vscroll_p : 1; + /* Amount by which lines of this window are scrolled in y-direction (smooth scrolling). */ int vscroll; diff --git a/src/xdisp.c b/src/xdisp.c index f09f209b2e3..b9b3c6d1bf3 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -19168,7 +19168,14 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) int new_vpos = -1; w->force_start = false; - w->vscroll = 0; + + /* The vscroll should be preserved in this case, since + `pixel-scroll-precision-mode' must continue working normally + when a mini-window is resized. (bug#55312) */ + if (!w->preserve_vscroll_p || !window_frozen_p (w)) + w->vscroll = 0; + + w->preserve_vscroll_p = false; w->window_end_valid = false; /* Forget any recorded base line for line number display. */ -- 2.39.2