> Date: Thu, 06 Jun 2013 20:32:15 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: 14567@debbugs.gnu.org
Can you try the changes below and see if they give good results,>
> > From: Thomas Wiecki <thomas.wiecki@gmail.com>
> > Date: Thu, 6 Jun 2013 13:16:43 -0400
> > Cc: 14567@debbugs.gnu.org
> >
> > 1. Download a large image (e.g.
> > http://cdn.urbanislandz.com/wp-content/uploads/2011/10/MMSposter-large.jpg)
> > and save it as /tmp/test.jpg
> > 2. In an emacs buffer type "(insert-image (create-image "/tmp/test.jpg"))"
> > 3. Type some arbitrary lines of text below this line.
> > 4. In first line (containing insert-image), type C-x C-e at end of line to
> > load the image.
> > 5. Image should appear in buffer.
> > 6. Scroll down repeatedly until past the image.
> >
> > Expected behavior: Scrolls down smoothly even once scrolled past image.
> > Observed behavior: Scrolls down smoothly until end of image is reached. At
> > end of image, the next scroll causes a huge jump in the window so that and
> > only the text is shown but not any of the residual image.
> >
> > 7. scroll back up
> >
> > Expected behavior: Scrolls upwards over image.
> > Observed behavior: Jumps over complete image and shows beginning of buffer.
>
> Perfect, thanks. I will take a look.
including in the real-life use cases where you bumped into this? Note
that you will have to rebuild Emacs to try this.
Thanks.
=== modified file 'lisp/simple.el'
--- lisp/simple.el 2013-06-05 18:10:27 +0000
+++ lisp/simple.el 2013-06-08 14:14:39 +0000
@@ -4738,20 +4738,35 @@ lines."
(vpos (nth 1 lh))
(ypos (nth 2 lh))
(rbot (nth 3 lh))
+ (this-lh (window-line-height))
+ (this-height (nth 0 this-lh))
+ (this-ypos (nth 2 this-lh))
+ (fch (frame-char-height))
py vs)
(when (or (null lh)
- (>= rbot (frame-char-height))
- (<= ypos (- (frame-char-height))))
+ (>= rbot fch)
+ (<= ypos (- fch))
+ (null this-lh)
+ (<= this-ypos (- fch)))
(unless lh
(let ((wend (pos-visible-in-window-p t nil t)))
(setq rbot (nth 3 wend)
vpos (nth 5 wend))))
+ (unless this-lh
+ (let ((wstart (pos-visible-in-window-p nil nil t)))
+ (setq this-ypos (nth 2 wstart)
+ this-height (nth 4 wstart))))
(cond
- ;; If last line of window is fully visible, move forward.
- ((or (null rbot) (= rbot 0))
+ ;; If last line of window is fully visible, and vscrolling
+ ;; more would make this line invisible, move forward.
+ ((and (or (< (setq vs (window-vscroll nil t)) fch)
+ (<= this-height fch))
+ (or (null rbot) (= rbot 0)))
nil)
- ;; If cursor is not in the bottom scroll margin, move forward.
- ((and (> vpos 0)
+ ;; If cursor is not in the bottom scroll margin, and the
+ ;; current line is is not too tall, move forward.
+ ((and (<= this-height fch)
+ (> vpos 0)
(< (setq py
(or (nth 1 (window-line-height))
(let ((ppos (posn-at-point)))
@@ -4761,9 +4776,10 @@ lines."
nil)
;; When already vscrolled, we vscroll some more if we can,
;; or clear vscroll and move forward at end of tall image.
- ((> (setq vs (window-vscroll nil t)) 0)
- (when (> rbot 0)
- (set-window-vscroll nil (+ vs (min rbot (frame-char-height))) t)))
+ ((> vs 0)
+ (when (or (> rbot 0)
+ (> this-height fch))
+ (set-window-vscroll nil (+ vs fch) t)))
;; If cursor just entered the bottom scroll margin, move forward,
;; but also vscroll one line so redisplay won't recenter.
((and (> vpos 0)
@@ -4808,7 +4824,14 @@ lines."
;; display-based motion doesn't make sense (because each
;; logical line occupies exactly one screen line).
(not (> (window-hscroll) 0)))
- (line-move-visual arg noerror)
+ (prog1 (line-move-visual arg noerror)
+ ;; If we moved into a tall line, set vscroll to make
+ ;; scrolling through tall images more smooth.
+ (let ((lh (line-pixel-height)))
+ (if (and (< arg 0)
+ (< (point) (window-start))
+ (> lh (frame-char-height)))
+ (set-window-vscroll nil (- lh (frame-char-height)) t))))
(line-move-1 arg noerror to-end)))))
;; Display-based alternative to line-move-1.
=== modified file 'src/xdisp.c'
--- src/xdisp.c 2013-06-06 16:35:31 +0000
+++ src/xdisp.c 2013-06-08 14:02:28 +0000
@@ -1217,6 +1217,24 @@ line_bottom_y (struct it *it)
return line_top_y + line_height;
}
+DEFUN ("line-pixel-height", Fline_pixel_height,
+ Sline_pixel_height, 0, 0, 0,
+ doc: /* Return height in pixels of text line in the selected window.
+
+Value is the height in pixels of the line at point. */)
+ (void)
+{
+ struct it it;
+ struct text_pos pt;
+ struct window *w = XWINDOW (selected_window);
+
+ SET_TEXT_POS (pt, PT, PT_BYTE);
+ start_display (&it, w, pt);
+ it.vpos = it.current_y = 0;
+ last_height = 0;
+ return make_number (line_bottom_y (&it));
+}
+
/* Subroutine of pos_visible_p below. Extracts a display string, if
any, from the display spec given as its argument. */
static Lisp_Object
@@ -28665,6 +28683,7 @@ syms_of_xdisp (void)
defsubr (&Stool_bar_lines_needed);
defsubr (&Slookup_image_map);
#endif
+ defsubr (&Sline_pixel_height);
defsubr (&Sformat_mode_line);
defsubr (&Sinvisible_p);
defsubr (&Scurrent_bidi_paragraph_direction);