0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 8.2.4902: mouse wheel scrolling is inconsistent

Problem:    Mouse wheel scrolling is inconsistent.
Solution:   Use the MS-Winows system setting. (closes #10368)
This commit is contained in:
LemonBoy
2022-05-07 12:25:40 +01:00
committed by Bram Moolenaar
parent 8e4b76da1d
commit c27747e6dd
7 changed files with 95 additions and 58 deletions

View File

@@ -237,31 +237,34 @@ it works depends on your system. It might also work in an xterm
|xterm-mouse-wheel|. By default only vertical scroll wheels are supported, |xterm-mouse-wheel|. By default only vertical scroll wheels are supported,
but some GUIs also support horizontal scroll wheels. but some GUIs also support horizontal scroll wheels.
For the Win32 GUI the scroll action is hard coded. It works just like On MS-Windows, if the scroll action causes input focus -problems, see
dragging the scrollbar of the current window. How many lines are scrolled |intellimouse-wheel-problems|.
depends on your mouse driver. If the scroll action causes input focus
problems, see |intellimouse-wheel-problems|.
For the X11 GUIs (Motif and GTK) scrolling the wheel generates key For Win32 and the X11 GUIs (Motif and GTK) scrolling the wheel generates key
presses <ScrollWheelUp>, <ScrollWheelDown>, <ScrollWheelLeft> and presses <ScrollWheelUp>, <ScrollWheelDown>, <ScrollWheelLeft> and
<ScrollWheelRight>. For example, if you push the scroll wheel upwards a <ScrollWheelRight>. For example, if you push the scroll wheel upwards a
<ScrollWheelUp> key press is generated causing the window to scroll upwards <ScrollWheelUp> key press is generated causing the window to scroll upwards
(while the text is actually moving downwards). The default action for these (while the text is actually moving downwards). The default action for these
keys are: keys are:
<ScrollWheelUp> scroll three lines up *<ScrollWheelUp>* <ScrollWheelUp> scroll N lines up *<ScrollWheelUp>*
<S-ScrollWheelUp> scroll one page up *<S-ScrollWheelUp>* <S-ScrollWheelUp> scroll one page up *<S-ScrollWheelUp>*
<C-ScrollWheelUp> scroll one page up *<C-ScrollWheelUp>* <C-ScrollWheelUp> scroll one page up *<C-ScrollWheelUp>*
<ScrollWheelDown> scroll three lines down *<ScrollWheelDown>* <ScrollWheelDown> scroll N lines down *<ScrollWheelDown>*
<S-ScrollWheelDown> scroll one page down *<S-ScrollWheelDown>* <S-ScrollWheelDown> scroll one page down *<S-ScrollWheelDown>*
<C-ScrollWheelDown> scroll one page down *<C-ScrollWheelDown>* <C-ScrollWheelDown> scroll one page down *<C-ScrollWheelDown>*
<ScrollWheelLeft> scroll six columns left *<ScrollWheelLeft>* <ScrollWheelLeft> scroll N columns left *<ScrollWheelLeft>*
<S-ScrollWheelLeft> scroll one page left *<S-ScrollWheelLeft>* <S-ScrollWheelLeft> scroll one page left *<S-ScrollWheelLeft>*
<C-ScrollWheelLeft> scroll one page left *<C-ScrollWheelLeft>* <C-ScrollWheelLeft> scroll one page left *<C-ScrollWheelLeft>*
<ScrollWheelRight> scroll six columns right *<ScrollWheelRight>* <ScrollWheelRight> scroll N columns right *<ScrollWheelRight>*
<S-ScrollWheelRight> scroll one page right *<S-ScrollWheelRight>* <S-ScrollWheelRight> scroll one page right *<S-ScrollWheelRight>*
<C-ScrollWheelRight> scroll one page right *<C-ScrollWheelRight>* <C-ScrollWheelRight> scroll one page right *<C-ScrollWheelRight>*
This should work in all modes, except when editing the command line. This should work in all modes, except when editing the command line.
The value of N depends on the system. By default Vim scrolls three lines when
moving vertically, and six columns when moving horizontally. On MS-Windows
the amount of lines and columns for each scroll action is taken from the
system-wide settings.
Note that horizontal scrolling only works if 'nowrap' is set. Also, unless Note that horizontal scrolling only works if 'nowrap' is set. Also, unless
the "h" flag in 'guioptions' is set, the cursor moves to the longest visible the "h" flag in 'guioptions' is set, the cursor moves to the longest visible
line if the cursor line is about to be scrolled off the screen (similarly to line if the cursor line is about to be scrolled off the screen (similarly to

View File

@@ -230,6 +230,10 @@ gui_mch_set_rendering_options(char_u *s)
# define SPI_GETWHEELSCROLLCHARS 0x006C # define SPI_GETWHEELSCROLLCHARS 0x006C
#endif #endif
#ifndef SPI_SETWHEELSCROLLCHARS
# define SPI_SETWHEELSCROLLCHARS 0x006D
#endif
#ifdef PROTO #ifdef PROTO
/* /*
* Define a few things for generating prototypes. This is just to avoid * Define a few things for generating prototypes. This is just to avoid
@@ -4117,19 +4121,33 @@ gui_mswin_get_menu_height(
/* /*
* Setup for the Intellimouse * Setup for the Intellimouse
*/ */
static long
mouse_vertical_scroll_step(void)
{
UINT val;
if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &val, 0))
return (val != WHEEL_PAGESCROLL) ? (long)val : -1;
return 3; // Safe default;
}
static long
mouse_horizontal_scroll_step(void)
{
UINT val;
if (SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &val, 0))
return (long)val;
return 3; // Safe default;
}
static void static void
init_mouse_wheel(void) init_mouse_wheel(void)
{ {
// Reasonable default values. // Get the default values for the horizontal and vertical scroll steps from
mouse_scroll_lines = 3; // the system.
mouse_scroll_chars = 3; mouse_set_vert_scroll_step(mouse_vertical_scroll_step());
mouse_set_hor_scroll_step(mouse_horizontal_scroll_step());
// if NT 4.0+ (or Win98) get scroll lines directly from system
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &mouse_scroll_lines, 0);
SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &mouse_scroll_chars, 0);
} }
/* /*
* Intellimouse wheel handler. * Intellimouse wheel handler.
* Treat a mouse wheel event as if it were a scroll request. * Treat a mouse wheel event as if it were a scroll request.
@@ -4137,16 +4155,10 @@ init_mouse_wheel(void)
static void static void
_OnMouseWheel(HWND hwnd, short zDelta, LPARAM param, int horizontal) _OnMouseWheel(HWND hwnd, short zDelta, LPARAM param, int horizontal)
{ {
int i;
int amount;
int button; int button;
win_T *wp; win_T *wp;
int modifiers, kbd_modifiers; int modifiers, kbd_modifiers;
// Initializes mouse_scroll_chars too.
if (mouse_scroll_lines == 0)
init_mouse_wheel();
wp = gui_mouse_window(FIND_POPUP); wp = gui_mouse_window(FIND_POPUP);
#ifdef FEAT_PROP_POPUP #ifdef FEAT_PROP_POPUP
@@ -4185,23 +4197,9 @@ _OnMouseWheel(HWND hwnd, short zDelta, LPARAM param, int horizontal)
// Translate the scroll event into an event that Vim can process so that // Translate the scroll event into an event that Vim can process so that
// the user has a chance to map the scrollwheel buttons. // the user has a chance to map the scrollwheel buttons.
if (horizontal) if (horizontal)
{
button = zDelta >= 0 ? MOUSE_6 : MOUSE_7; button = zDelta >= 0 ? MOUSE_6 : MOUSE_7;
if (mouse_scroll_chars > 0
&& mouse_scroll_chars < MAX(wp->w_width - 2, 1))
amount = mouse_scroll_chars;
else
amount = MAX(wp->w_width - 2, 1);
}
else else
{
button = zDelta >= 0 ? MOUSE_4 : MOUSE_5; button = zDelta >= 0 ? MOUSE_4 : MOUSE_5;
if (mouse_scroll_lines > 0
&& mouse_scroll_lines < MAX(wp->w_height - 2, 1))
amount = mouse_scroll_lines;
else
amount = MAX(wp->w_height - 2, 1);
}
kbd_modifiers = get_active_modifiers(); kbd_modifiers = get_active_modifiers();
@@ -4213,8 +4211,7 @@ _OnMouseWheel(HWND hwnd, short zDelta, LPARAM param, int horizontal)
modifiers |= MOUSE_ALT; modifiers |= MOUSE_ALT;
mch_disable_flush(); mch_disable_flush();
for (i = amount; i > 0; --i) gui_send_mouse_event(button, GET_X_LPARAM(param), GET_Y_LPARAM(param),
gui_send_mouse_event(button, GET_X_LPARAM(param), GET_Y_LPARAM(param),
FALSE, kbd_modifiers); FALSE, kbd_modifiers);
mch_enable_flush(); mch_enable_flush();
gui_may_flush(); gui_may_flush();
@@ -4296,12 +4293,10 @@ _OnSettingChange(UINT param)
switch (param) switch (param)
{ {
case SPI_SETWHEELSCROLLLINES: case SPI_SETWHEELSCROLLLINES:
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, mouse_set_vert_scroll_step(mouse_vertical_scroll_step());
&mouse_scroll_lines, 0);
break; break;
case SPI_GETWHEELSCROLLCHARS: case SPI_SETWHEELSCROLLCHARS:
SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, mouse_set_hor_scroll_step(mouse_horizontal_scroll_step());
&mouse_scroll_chars, 0);
break; break;
case SPI_SETNONCLIENTMETRICS: case SPI_SETNONCLIENTMETRICS:
set_tabline_font(); set_tabline_font();

View File

@@ -13,6 +13,25 @@
#include "vim.h" #include "vim.h"
/*
* Horiziontal and vertical steps used when scrolling.
* When negative scroll by a whole page.
*/
static long mouse_hor_step = 6;
static long mouse_vert_step = 3;
void
mouse_set_vert_scroll_step(long step)
{
mouse_vert_step = step;
}
void
mouse_set_hor_scroll_step(long step)
{
mouse_hor_step = step;
}
#ifdef CHECK_DOUBLE_CLICK #ifdef CHECK_DOUBLE_CLICK
/* /*
* Return the duration from t1 to t2 in milliseconds. * Return the duration from t1 to t2 in milliseconds.
@@ -1101,13 +1120,16 @@ ins_mousescroll(int dir)
// Don't scroll the window in which completion is being done. // Don't scroll the window in which completion is being done.
if (!pum_visible() || curwin != old_curwin) if (!pum_visible() || curwin != old_curwin)
{ {
long step;
if (dir == MSCR_DOWN || dir == MSCR_UP) if (dir == MSCR_DOWN || dir == MSCR_UP)
{ {
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) if (mouse_vert_step < 0
scroll_redraw(dir, || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
(long)(curwin->w_botline - curwin->w_topline)); step = (long)(curwin->w_botline - curwin->w_topline);
else else
scroll_redraw(dir, 3L); step = mouse_vert_step;
scroll_redraw(dir, step);
# ifdef FEAT_PROP_POPUP # ifdef FEAT_PROP_POPUP
if (WIN_IS_POPUP(curwin)) if (WIN_IS_POPUP(curwin))
popup_set_firstline(curwin); popup_set_firstline(curwin);
@@ -1116,10 +1138,13 @@ ins_mousescroll(int dir)
#ifdef FEAT_GUI #ifdef FEAT_GUI
else else
{ {
int val, step = 6; int val;
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) if (mouse_hor_step < 0
|| mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
step = curwin->w_width; step = curwin->w_width;
else
step = mouse_hor_step;
val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step); val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step);
if (val < 0) if (val < 0)
val = 0; val = 0;
@@ -2005,8 +2030,9 @@ retnomove:
} }
/* /*
* Mouse scroll wheel: Default action is to scroll three lines, or one page * Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or
* when Shift or Ctrl is used. * mouse_hor_step, depending on the scroll direction), or one page when Shift or
* Ctrl is used.
* K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or
* K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2) * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2)
*/ */
@@ -2033,7 +2059,6 @@ nv_mousescroll(cmdarg_T *cap)
curwin = wp; curwin = wp;
curbuf = curwin->w_buffer; curbuf = curwin->w_buffer;
} }
if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
{ {
# ifdef FEAT_TERMINAL # ifdef FEAT_TERMINAL
@@ -2043,21 +2068,21 @@ nv_mousescroll(cmdarg_T *cap)
send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE); send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
else else
# endif # endif
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) if (mouse_vert_step < 0 || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
{ {
(void)onepage(cap->arg ? FORWARD : BACKWARD, 1L); (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L);
} }
else else
{ {
// Don't scroll more than half the window height. // Don't scroll more than half the window height.
if (curwin->w_height < 6) if (curwin->w_height < mouse_vert_step * 2)
{ {
cap->count1 = curwin->w_height / 2; cap->count1 = curwin->w_height / 2;
if (cap->count1 == 0) if (cap->count1 == 0)
cap->count1 = 1; cap->count1 = 1;
} }
else else
cap->count1 = 3; cap->count1 = mouse_vert_step;
cap->count0 = cap->count1; cap->count0 = cap->count1;
nv_scroll_line(cap); nv_scroll_line(cap);
} }
@@ -2072,10 +2097,13 @@ nv_mousescroll(cmdarg_T *cap)
// Horizontal scroll - only allowed when 'wrap' is disabled // Horizontal scroll - only allowed when 'wrap' is disabled
if (!curwin->w_p_wrap) if (!curwin->w_p_wrap)
{ {
int val, step = 6; int val, step;
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) if (mouse_hor_step < 0
|| mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
step = curwin->w_width; step = curwin->w_width;
else
step = mouse_hor_step;
val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step); val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step);
if (val < 0) if (val < 0)
val = 0; val = 0;

View File

@@ -1,4 +1,6 @@
/* mouse.c */ /* mouse.c */
void mouse_set_vert_scroll_step(long step);
void mouse_set_hor_scroll_step(long step);
int do_mouse(oparg_T *oap, int c, int dir, long count, int fixindent); int do_mouse(oparg_T *oap, int c, int dir, long count, int fixindent);
void ins_mouse(int c); void ins_mouse(int c);
void ins_mousescroll(int dir); void ins_mousescroll(int dir);

View File

@@ -997,6 +997,7 @@ func Test_gui_mouse_event()
call assert_equal(['one two abc three', 'four five posix'], getline(1, '$')) call assert_equal(['one two abc three', 'four five posix'], getline(1, '$'))
%d _ %d _
set scrolloff=0
call setline(1, range(1, 100)) call setline(1, range(1, 100))
" scroll up " scroll up
let args = #{button: 0x200, row: 2, col: 1, multiclick: 0, modifiers: 0} let args = #{button: 0x200, row: 2, col: 1, multiclick: 0, modifiers: 0}
@@ -1012,6 +1013,7 @@ func Test_gui_mouse_event()
call test_gui_event('mouse', args) call test_gui_event('mouse', args)
call feedkeys("H", 'Lx!') call feedkeys("H", 'Lx!')
call assert_equal(4, line('.')) call assert_equal(4, line('.'))
set scrolloff&
%d _ %d _
set nowrap set nowrap

View File

@@ -1393,6 +1393,11 @@ test_gui_mouse_event(dict_T *args)
repeated_click = (int)dict_get_number(args, (char_u *)"multiclick"); repeated_click = (int)dict_get_number(args, (char_u *)"multiclick");
mods = (int)dict_get_number(args, (char_u *)"modifiers"); mods = (int)dict_get_number(args, (char_u *)"modifiers");
// Reset the scroll values to known values.
// XXX: Remove this when/if the scroll step is made configurable.
mouse_set_hor_scroll_step(6);
mouse_set_vert_scroll_step(3);
gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1),
repeated_click, mods); repeated_click, mods);
} }

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
4902,
/**/ /**/
4901, 4901,
/**/ /**/