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:
@@ -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
|
||||||
|
@@ -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();
|
||||||
|
56
src/mouse.c
56
src/mouse.c
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user