aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNoam Postavsky2017-02-02 21:35:51 -0500
committerNoam Postavsky2017-02-02 21:35:51 -0500
commitce88155d83ba84e84321ed69a39c82f40117dd1f (patch)
treeb56e2f89a597cb407747639c02333dde7e4552ba /src
parent604724e49d7b44dc663ad941998a0a44aa4fc178 (diff)
parentda515a0d8e97d89a1c7e60faea190174a8c72618 (diff)
downloademacs-ce88155d83ba84e84321ed69a39c82f40117dd1f.tar.gz
emacs-ce88155d83ba84e84321ed69a39c82f40117dd1f.zip
; Merge: fixes and updates to scroll margin (Bug#5718)
- add new option `maximum-sroll-margin' - refactor and fix scroll margin calculation
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h1
-rw-r--r--src/window.c53
-rw-r--r--src/window.h2
-rw-r--r--src/xdisp.c104
4 files changed, 84 insertions, 76 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 51222e636be..eb71a82311c 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3263,6 +3263,7 @@ void move_it_past_eol (struct it *);
3263void move_it_in_display_line (struct it *it, 3263void move_it_in_display_line (struct it *it,
3264 ptrdiff_t to_charpos, int to_x, 3264 ptrdiff_t to_charpos, int to_x,
3265 enum move_operation_enum op); 3265 enum move_operation_enum op);
3266int partial_line_height (struct it *it_origin);
3266bool in_display_vector_p (struct it *); 3267bool in_display_vector_p (struct it *);
3267int frame_mode_line_height (struct frame *); 3268int frame_mode_line_height (struct frame *);
3268extern bool redisplaying_p; 3269extern bool redisplaying_p;
diff --git a/src/window.c b/src/window.c
index bc3f488f37f..95690443f8e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4790,6 +4790,36 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
4790 XWINDOW (window)->window_end_valid = false; 4790 XWINDOW (window)->window_end_valid = false;
4791} 4791}
4792 4792
4793/* Compute scroll margin for WINDOW.
4794 We scroll when point is within this distance from the top or bottom
4795 of the window. The result is measured in lines or in pixels
4796 depending on the second parameter. */
4797int
4798window_scroll_margin (struct window *window, enum margin_unit unit)
4799{
4800 if (scroll_margin > 0)
4801 {
4802 int frame_line_height = default_line_pixel_height (window);
4803 int window_lines = window_box_height (window) / frame_line_height;
4804
4805 double ratio = 0.25;
4806 if (FLOATP (Vmaximum_scroll_margin))
4807 {
4808 ratio = XFLOAT_DATA (Vmaximum_scroll_margin);
4809 ratio = max (0.0, ratio);
4810 ratio = min (ratio, 0.5);
4811 }
4812 int max_margin = min ((window_lines - 1)/2,
4813 (int) (window_lines * ratio));
4814 int margin = clip_to_bounds (0, scroll_margin, max_margin);
4815 return (unit == MARGIN_IN_PIXELS)
4816 ? margin * frame_line_height
4817 : margin;
4818 }
4819 else
4820 return 0;
4821}
4822
4793 4823
4794/* Implementation of window_scroll that works based on pixel line 4824/* Implementation of window_scroll that works based on pixel line
4795 heights. See the comment of window_scroll for parameter 4825 heights. See the comment of window_scroll for parameter
@@ -4806,7 +4836,6 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
4806 bool vscrolled = false; 4836 bool vscrolled = false;
4807 int x, y, rtop, rbot, rowh, vpos; 4837 int x, y, rtop, rbot, rowh, vpos;
4808 void *itdata = NULL; 4838 void *itdata = NULL;
4809 int window_total_lines;
4810 int frame_line_height = default_line_pixel_height (w); 4839 int frame_line_height = default_line_pixel_height (w);
4811 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window), 4840 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
4812 Fwindow_old_point (window))); 4841 Fwindow_old_point (window)));
@@ -5062,12 +5091,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
5062 /* Move PT out of scroll margins. 5091 /* Move PT out of scroll margins.
5063 This code wants current_y to be zero at the window start position 5092 This code wants current_y to be zero at the window start position
5064 even if there is a header line. */ 5093 even if there is a header line. */
5065 window_total_lines 5094 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
5066 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
5067 this_scroll_margin = max (0, scroll_margin);
5068 this_scroll_margin
5069 = min (this_scroll_margin, window_total_lines / 4);
5070 this_scroll_margin *= frame_line_height;
5071 5095
5072 if (n > 0) 5096 if (n > 0)
5073 { 5097 {
@@ -5123,7 +5147,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
5123 in the scroll margin at the bottom. */ 5147 in the scroll margin at the bottom. */
5124 move_it_to (&it, PT, -1, 5148 move_it_to (&it, PT, -1,
5125 (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w) 5149 (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w)
5126 - this_scroll_margin - 1), 5150 - partial_line_height (&it) - this_scroll_margin - 1),
5127 -1, 5151 -1,
5128 MOVE_TO_POS | MOVE_TO_Y); 5152 MOVE_TO_POS | MOVE_TO_Y);
5129 5153
@@ -5290,9 +5314,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5290 5314
5291 if (pos < ZV) 5315 if (pos < ZV)
5292 { 5316 {
5293 /* Don't use a scroll margin that is negative or too large. */ 5317 int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
5294 int this_scroll_margin =
5295 max (0, min (scroll_margin, w->total_lines / 4));
5296 5318
5297 set_marker_restricted_both (w->start, w->contents, pos, pos_byte); 5319 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
5298 w->start_at_line_beg = !NILP (bolp); 5320 w->start_at_line_beg = !NILP (bolp);
@@ -5722,8 +5744,7 @@ and redisplay normally--don't erase and redraw the frame. */)
5722 5744
5723 /* Do this after making BUF current 5745 /* Do this after making BUF current
5724 in case scroll_margin is buffer-local. */ 5746 in case scroll_margin is buffer-local. */
5725 this_scroll_margin 5747 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
5726 = max (0, min (scroll_margin, w->total_lines / 4));
5727 5748
5728 /* Don't use redisplay code for initial frames, as the necessary 5749 /* Don't use redisplay code for initial frames, as the necessary
5729 data structures might not be set up yet then. */ 5750 data structures might not be set up yet then. */
@@ -5962,10 +5983,6 @@ from the top of the window. */)
5962 5983
5963 lines = displayed_window_lines (w); 5984 lines = displayed_window_lines (w);
5964 5985
5965#if false
5966 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5967#endif
5968
5969 if (NILP (arg)) 5986 if (NILP (arg))
5970 XSETFASTINT (arg, lines / 2); 5987 XSETFASTINT (arg, lines / 2);
5971 else 5988 else
@@ -5981,6 +5998,8 @@ from the top of the window. */)
5981 it is probably better not to install it. However, it is here 5998 it is probably better not to install it. However, it is here
5982 inside #if false so as not to lose it. -- rms. */ 5999 inside #if false so as not to lose it. -- rms. */
5983 6000
6001 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
6002
5984 /* Don't let it get into the margin at either top or bottom. */ 6003 /* Don't let it get into the margin at either top or bottom. */
5985 iarg = max (iarg, this_scroll_margin); 6004 iarg = max (iarg, this_scroll_margin);
5986 iarg = min (iarg, lines - this_scroll_margin - 1); 6005 iarg = min (iarg, lines - this_scroll_margin - 1);
diff --git a/src/window.h b/src/window.h
index 061cf244943..acb8a5cabfa 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1120,6 +1120,8 @@ extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
1120extern void mark_window_cursors_off (struct window *); 1120extern void mark_window_cursors_off (struct window *);
1121extern int window_internal_height (struct window *); 1121extern int window_internal_height (struct window *);
1122extern int window_body_width (struct window *w, bool); 1122extern int window_body_width (struct window *w, bool);
1123enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
1124extern int window_scroll_margin (struct window *, enum margin_unit);
1123extern void temp_output_buffer_show (Lisp_Object); 1125extern void temp_output_buffer_show (Lisp_Object);
1124extern void replace_buffer_in_windows (Lisp_Object); 1126extern void replace_buffer_in_windows (Lisp_Object);
1125extern void replace_buffer_in_windows_safely (Lisp_Object); 1127extern void replace_buffer_in_windows_safely (Lisp_Object);
diff --git a/src/xdisp.c b/src/xdisp.c
index 33661c882cd..0e329dfe6e9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -9859,6 +9859,32 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
9859 } 9859 }
9860} 9860}
9861 9861
9862int
9863partial_line_height (struct it *it_origin)
9864{
9865 int partial_height;
9866 void *it_data = NULL;
9867 struct it it;
9868 SAVE_IT (it, *it_origin, it_data);
9869 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
9870 MOVE_TO_POS | MOVE_TO_Y);
9871 if (it.what == IT_EOB)
9872 {
9873 int vis_height = it.last_visible_y - it.current_y;
9874 int height = it.ascent + it.descent;
9875 partial_height = (vis_height < height) ? vis_height : 0;
9876 }
9877 else
9878 {
9879 int last_line_y = it.current_y;
9880 move_it_by_lines (&it, 1);
9881 partial_height = (it.current_y > it.last_visible_y)
9882 ? it.last_visible_y - last_line_y : 0;
9883 }
9884 RESTORE_IT (&it, &it, it_data);
9885 return partial_height;
9886}
9887
9862/* Return true if IT points into the middle of a display vector. */ 9888/* Return true if IT points into the middle of a display vector. */
9863 9889
9864bool 9890bool
@@ -15316,7 +15342,6 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
15316 bool temp_scroll_step, bool last_line_misfit) 15342 bool temp_scroll_step, bool last_line_misfit)
15317{ 15343{
15318 struct window *w = XWINDOW (window); 15344 struct window *w = XWINDOW (window);
15319 struct frame *f = XFRAME (w->frame);
15320 struct text_pos pos, startp; 15345 struct text_pos pos, startp;
15321 struct it it; 15346 struct it it;
15322 int this_scroll_margin, scroll_max, rc, height; 15347 int this_scroll_margin, scroll_max, rc, height;
@@ -15327,8 +15352,6 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
15327 /* We will never try scrolling more than this number of lines. */ 15352 /* We will never try scrolling more than this number of lines. */
15328 int scroll_limit = SCROLL_LIMIT; 15353 int scroll_limit = SCROLL_LIMIT;
15329 int frame_line_height = default_line_pixel_height (w); 15354 int frame_line_height = default_line_pixel_height (w);
15330 int window_total_lines
15331 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
15332 15355
15333#ifdef GLYPH_DEBUG 15356#ifdef GLYPH_DEBUG
15334 debug_method_add (w, "try_scrolling"); 15357 debug_method_add (w, "try_scrolling");
@@ -15336,13 +15359,7 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
15336 15359
15337 SET_TEXT_POS_FROM_MARKER (startp, w->start); 15360 SET_TEXT_POS_FROM_MARKER (startp, w->start);
15338 15361
15339 /* Compute scroll margin height in pixels. We scroll when point is 15362 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
15340 within this distance from the top or bottom of the window. */
15341 if (scroll_margin > 0)
15342 this_scroll_margin = min (scroll_margin, window_total_lines / 4)
15343 * frame_line_height;
15344 else
15345 this_scroll_margin = 0;
15346 15363
15347 /* Force arg_scroll_conservatively to have a reasonable value, to 15364 /* Force arg_scroll_conservatively to have a reasonable value, to
15348 avoid scrolling too far away with slow move_it_* functions. Note 15365 avoid scrolling too far away with slow move_it_* functions. Note
@@ -15377,7 +15394,8 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
15377 /* Compute the pixel ypos of the scroll margin, then move IT to 15394 /* Compute the pixel ypos of the scroll margin, then move IT to
15378 either that ypos or PT, whichever comes first. */ 15395 either that ypos or PT, whichever comes first. */
15379 start_display (&it, w, startp); 15396 start_display (&it, w, startp);
15380 scroll_margin_y = it.last_visible_y - this_scroll_margin 15397 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
15398 - this_scroll_margin
15381 - frame_line_height * extra_scroll_margin_lines; 15399 - frame_line_height * extra_scroll_margin_lines;
15382 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1, 15400 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
15383 (MOVE_TO_POS | MOVE_TO_Y)); 15401 (MOVE_TO_POS | MOVE_TO_Y));
@@ -15816,23 +15834,12 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
15816 { 15834 {
15817 int this_scroll_margin, top_scroll_margin; 15835 int this_scroll_margin, top_scroll_margin;
15818 struct glyph_row *row = NULL; 15836 struct glyph_row *row = NULL;
15819 int frame_line_height = default_line_pixel_height (w);
15820 int window_total_lines
15821 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
15822 15837
15823#ifdef GLYPH_DEBUG 15838#ifdef GLYPH_DEBUG
15824 debug_method_add (w, "cursor movement"); 15839 debug_method_add (w, "cursor movement");
15825#endif 15840#endif
15826 15841
15827 /* Scroll if point within this distance from the top or bottom 15842 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
15828 of the window. This is a pixel value. */
15829 if (scroll_margin > 0)
15830 {
15831 this_scroll_margin = min (scroll_margin, window_total_lines / 4);
15832 this_scroll_margin *= frame_line_height;
15833 }
15834 else
15835 this_scroll_margin = 0;
15836 15843
15837 top_scroll_margin = this_scroll_margin; 15844 top_scroll_margin = this_scroll_margin;
15838 if (WINDOW_WANTS_HEADER_LINE_P (w)) 15845 if (WINDOW_WANTS_HEADER_LINE_P (w))
@@ -16280,7 +16287,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16280 int centering_position = -1; 16287 int centering_position = -1;
16281 bool last_line_misfit = false; 16288 bool last_line_misfit = false;
16282 ptrdiff_t beg_unchanged, end_unchanged; 16289 ptrdiff_t beg_unchanged, end_unchanged;
16283 int frame_line_height; 16290 int frame_line_height, margin;
16284 bool use_desired_matrix; 16291 bool use_desired_matrix;
16285 void *itdata = NULL; 16292 void *itdata = NULL;
16286 16293
@@ -16310,6 +16317,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16310 restart: 16317 restart:
16311 reconsider_clip_changes (w); 16318 reconsider_clip_changes (w);
16312 frame_line_height = default_line_pixel_height (w); 16319 frame_line_height = default_line_pixel_height (w);
16320 margin = window_scroll_margin (w, MARGIN_IN_LINES);
16321
16313 16322
16314 /* Has the mode line to be updated? */ 16323 /* Has the mode line to be updated? */
16315 update_mode_line = (w->update_mode_line 16324 update_mode_line = (w->update_mode_line
@@ -16614,10 +16623,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16614 /* Some people insist on not letting point enter the scroll 16623 /* Some people insist on not letting point enter the scroll
16615 margin, even though this part handles windows that didn't 16624 margin, even though this part handles windows that didn't
16616 scroll at all. */ 16625 scroll at all. */
16617 int window_total_lines 16626 int pixel_margin = margin * frame_line_height;
16618 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
16619 int margin = min (scroll_margin, window_total_lines / 4);
16620 int pixel_margin = margin * frame_line_height;
16621 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w); 16627 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
16622 16628
16623 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop 16629 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
@@ -16901,12 +16907,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16901 it.current_y = it.last_visible_y; 16907 it.current_y = it.last_visible_y;
16902 if (centering_position < 0) 16908 if (centering_position < 0)
16903 { 16909 {
16904 int window_total_lines
16905 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
16906 int margin
16907 = scroll_margin > 0
16908 ? min (scroll_margin, window_total_lines / 4)
16909 : 0;
16910 ptrdiff_t margin_pos = CHARPOS (startp); 16910 ptrdiff_t margin_pos = CHARPOS (startp);
16911 Lisp_Object aggressive; 16911 Lisp_Object aggressive;
16912 bool scrolling_up; 16912 bool scrolling_up;
@@ -17150,10 +17150,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
17150 { 17150 {
17151 int window_total_lines 17151 int window_total_lines
17152 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height; 17152 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
17153 int margin =
17154 scroll_margin > 0
17155 ? min (scroll_margin, window_total_lines / 4)
17156 : 0;
17157 bool move_down = w->cursor.vpos >= window_total_lines / 2; 17153 bool move_down = w->cursor.vpos >= window_total_lines / 2;
17158 17154
17159 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1)); 17155 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
@@ -17359,7 +17355,6 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
17359 struct it it; 17355 struct it it;
17360 struct glyph_row *last_text_row = NULL; 17356 struct glyph_row *last_text_row = NULL;
17361 struct frame *f = XFRAME (w->frame); 17357 struct frame *f = XFRAME (w->frame);
17362 int frame_line_height = default_line_pixel_height (w);
17363 17358
17364 /* Make POS the new window start. */ 17359 /* Make POS the new window start. */
17365 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos)); 17360 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
@@ -17385,17 +17380,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
17385 if ((flags & TRY_WINDOW_CHECK_MARGINS) 17380 if ((flags & TRY_WINDOW_CHECK_MARGINS)
17386 && !MINI_WINDOW_P (w)) 17381 && !MINI_WINDOW_P (w))
17387 { 17382 {
17388 int this_scroll_margin; 17383 int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
17389 int window_total_lines
17390 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
17391
17392 if (scroll_margin > 0)
17393 {
17394 this_scroll_margin = min (scroll_margin, window_total_lines / 4);
17395 this_scroll_margin *= frame_line_height;
17396 }
17397 else
17398 this_scroll_margin = 0;
17399 17384
17400 if ((w->cursor.y >= 0 /* not vscrolled */ 17385 if ((w->cursor.y >= 0 /* not vscrolled */
17401 && w->cursor.y < this_scroll_margin 17386 && w->cursor.y < this_scroll_margin
@@ -18679,15 +18664,8 @@ try_window_id (struct window *w)
18679 18664
18680 /* Don't let the cursor end in the scroll margins. */ 18665 /* Don't let the cursor end in the scroll margins. */
18681 { 18666 {
18682 int this_scroll_margin, cursor_height; 18667 int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18683 int frame_line_height = default_line_pixel_height (w); 18668 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
18684 int window_total_lines
18685 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (it.f) / frame_line_height;
18686
18687 this_scroll_margin =
18688 max (0, min (scroll_margin, window_total_lines / 4));
18689 this_scroll_margin *= frame_line_height;
18690 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
18691 18669
18692 if ((w->cursor.y < this_scroll_margin 18670 if ((w->cursor.y < this_scroll_margin
18693 && CHARPOS (start) > BEGV) 18671 && CHARPOS (start) > BEGV)
@@ -31569,6 +31547,14 @@ Recenter the window whenever point gets within this many lines
31569of the top or bottom of the window. */); 31547of the top or bottom of the window. */);
31570 scroll_margin = 0; 31548 scroll_margin = 0;
31571 31549
31550 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
31551 doc: /* Maximum effective value of `scroll-margin'.
31552Given as a fraction of the current window's lines. The value should
31553be a floating point number between 0.0 and 0.5. The effective maximum
31554is limited to (/ (1- window-lines) 2). Non-float values for this
31555variable are ignored and the default 0.25 is used instead. */);
31556 Vmaximum_scroll_margin = make_float (0.25);
31557
31572 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch, 31558 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
31573 doc: /* Pixels per inch value for non-window system displays. 31559 doc: /* Pixels per inch value for non-window system displays.
31574Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */); 31560Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);