diff options
| author | Eli Zaretskii | 2020-12-14 20:23:24 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2020-12-14 20:23:24 +0200 |
| commit | 47a854bf24c8a36bf1e8ac32c8b5c9ebcba1d90a (patch) | |
| tree | 4c70876a8282aecef5aed00b70744b0bc619f274 /src | |
| parent | 2f1441cbe3ccd49037e2464485658f7f20f3d804 (diff) | |
| download | emacs-47a854bf24c8a36bf1e8ac32c8b5c9ebcba1d90a.tar.gz emacs-47a854bf24c8a36bf1e8ac32c8b5c9ebcba1d90a.zip | |
Improve accuracy of scrolling commands
* src/xdisp.c (move_it_vertically_backward): Don't rely on
line_bottom_y for accurate calculation of the next screen line's Y
coordinate: it doesn't work when the current screen line was not
yet traversed. Instead, record the previous Y coordinate and
reseat there if overshoot is detected.
* src/window.c (window_scroll_pixel_based): Calculate the new
window-start point more accurately when screen lines have uneven
height. (Bug#8355)
Diffstat (limited to 'src')
| -rw-r--r-- | src/window.c | 36 | ||||
| -rw-r--r-- | src/xdisp.c | 13 |
2 files changed, 28 insertions, 21 deletions
diff --git a/src/window.c b/src/window.c index 8e75e460b2b..4eab786958f 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -5686,27 +5686,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5686 | we would end up at the start of the line ending at ZV. */ | 5686 | we would end up at the start of the line ending at ZV. */ |
| 5687 | if (dy <= 0) | 5687 | if (dy <= 0) |
| 5688 | { | 5688 | { |
| 5689 | goal_y = it.current_y - dy; | 5689 | goal_y = it.current_y + dy; |
| 5690 | move_it_vertically_backward (&it, -dy); | 5690 | move_it_vertically_backward (&it, -dy); |
| 5691 | /* Extra precision for people who want us to preserve the | 5691 | /* move_it_vertically_backward above always overshoots if DY |
| 5692 | screen position of the cursor: effectively round DY to the | 5692 | cannot be reached exactly, i.e. if it falls in the middle |
| 5693 | nearest screen line, instead of rounding to zero; the latter | 5693 | of a screen line. But if that screen line is large |
| 5694 | causes point to move by one line after C-v followed by M-v, | 5694 | (e.g., a tall image), it might make more sense to |
| 5695 | if the buffer has lines of different height. */ | 5695 | undershoot instead. */ |
| 5696 | if (!NILP (Vscroll_preserve_screen_position) | 5696 | if (goal_y - it.current_y > 0.5 * flh) |
| 5697 | && it.current_y - goal_y > 0.5 * flh) | ||
| 5698 | { | 5697 | { |
| 5699 | it_data = bidi_shelve_cache (); | 5698 | it_data = bidi_shelve_cache (); |
| 5700 | struct it it2 = it; | 5699 | struct it it1 = it; |
| 5701 | 5700 | if (line_bottom_y (&it1) - goal_y < goal_y - it.current_y) | |
| 5702 | move_it_by_lines (&it, -1); | 5701 | move_it_by_lines (&it, 1); |
| 5703 | if (it.current_y < goal_y - 0.5 * flh) | 5702 | bidi_unshelve_cache (it_data, true); |
| 5704 | { | ||
| 5705 | it = it2; | ||
| 5706 | bidi_unshelve_cache (it_data, false); | ||
| 5707 | } | ||
| 5708 | else | ||
| 5709 | bidi_unshelve_cache (it_data, true); | ||
| 5710 | } | 5703 | } |
| 5711 | /* Ensure we actually do move, e.g. in case we are currently | 5704 | /* Ensure we actually do move, e.g. in case we are currently |
| 5712 | looking at an image that is taller that the window height. */ | 5705 | looking at an image that is taller that the window height. */ |
| @@ -5718,8 +5711,11 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5718 | { | 5711 | { |
| 5719 | goal_y = it.current_y + dy; | 5712 | goal_y = it.current_y + dy; |
| 5720 | move_it_to (&it, ZV, -1, goal_y, -1, MOVE_TO_POS | MOVE_TO_Y); | 5713 | move_it_to (&it, ZV, -1, goal_y, -1, MOVE_TO_POS | MOVE_TO_Y); |
| 5721 | /* See the comment above, for the reasons of this | 5714 | /* Extra precision for people who want us to preserve the |
| 5722 | extra-precision. */ | 5715 | screen position of the cursor: effectively round DY to the |
| 5716 | nearest screen line, instead of rounding to zero; the latter | ||
| 5717 | causes point to move by one line after C-v followed by M-v, | ||
| 5718 | if the buffer has lines of different height. */ | ||
| 5723 | if (!NILP (Vscroll_preserve_screen_position) | 5719 | if (!NILP (Vscroll_preserve_screen_position) |
| 5724 | && goal_y - it.current_y > 0.5 * flh) | 5720 | && goal_y - it.current_y > 0.5 * flh) |
| 5725 | { | 5721 | { |
diff --git a/src/xdisp.c b/src/xdisp.c index 96dd4fade25..699183f3f59 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -10301,11 +10301,22 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 10301 | move_it_vertically (it, target_y - it->current_y); | 10301 | move_it_vertically (it, target_y - it->current_y); |
| 10302 | else | 10302 | else |
| 10303 | { | 10303 | { |
| 10304 | struct text_pos last_pos; | ||
| 10305 | int last_y, last_vpos; | ||
| 10304 | do | 10306 | do |
| 10305 | { | 10307 | { |
| 10308 | last_pos = it->current.pos; | ||
| 10309 | last_y = it->current_y; | ||
| 10310 | last_vpos = it->vpos; | ||
| 10306 | move_it_by_lines (it, 1); | 10311 | move_it_by_lines (it, 1); |
| 10307 | } | 10312 | } |
| 10308 | while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV); | 10313 | while (target_y > it->current_y && IT_CHARPOS (*it) < ZV); |
| 10314 | if (it->current_y > target_y) | ||
| 10315 | { | ||
| 10316 | reseat (it, last_pos, true); | ||
| 10317 | it->current_y = last_y; | ||
| 10318 | it->vpos = last_vpos; | ||
| 10319 | } | ||
| 10309 | } | 10320 | } |
| 10310 | } | 10321 | } |
| 10311 | } | 10322 | } |