Skip to content

Commit ff95ce0

Browse files
zewpobrammool
authored andcommitted
patch 9.0.0906: mouse scroll code is not optimal
Problem: Mouse scroll code is not optimal. Solution: Properly organise Normal mode, Insert mode and common code. (Christopher Plewright, closes #11572)
1 parent 02edfaa commit ff95ce0

2 files changed

Lines changed: 113 additions & 83 deletions

File tree

src/mouse.c

Lines changed: 111 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,8 +1102,81 @@ ins_mouse(int c)
11021102
}
11031103

11041104
/*
1105-
* Implementation for scrolling in Insert mode in direction "dir", which is one
1106-
* of the MSCR_ values.
1105+
* Common mouse wheel scrolling, shared between Insert mode and NV modes.
1106+
* Default action is to scroll mouse_vert_step lines (or mouse_hor_step columns
1107+
* depending on the scroll direction) or one page when Shift or Ctrl is used.
1108+
* Direction is indicated by "cap->arg":
1109+
* K_MOUSEUP - MSCR_UP
1110+
* K_MOUSEDOWN - MSCR_DOWN
1111+
* K_MOUSELEFT - MSCR_LEFT
1112+
* K_MOUSERIGHT - MSCR_RIGHT
1113+
* "curwin" may have been changed to the window that should be scrolled and
1114+
* differ from the window that actually has focus.
1115+
*/
1116+
static void
1117+
do_mousescroll(cmdarg_T *cap)
1118+
{
1119+
int shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL);
1120+
1121+
#ifdef FEAT_TERMINAL
1122+
if (term_use_loop())
1123+
// This window is a terminal window, send the mouse event there.
1124+
// Set "typed" to FALSE to avoid an endless loop.
1125+
send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
1126+
else
1127+
#endif
1128+
if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
1129+
{
1130+
// Vertical scrolling
1131+
if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl))
1132+
{
1133+
// whole page up or down
1134+
onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L);
1135+
}
1136+
else
1137+
{
1138+
if (mouse_vert_step < 0 || shift_or_ctrl)
1139+
{
1140+
// whole page up or down
1141+
cap->count1 = (long)(curwin->w_botline - curwin->w_topline);
1142+
}
1143+
// Don't scroll more than half the window height.
1144+
else if (curwin->w_height < mouse_vert_step * 2)
1145+
{
1146+
cap->count1 = curwin->w_height / 2;
1147+
if (cap->count1 == 0)
1148+
cap->count1 = 1;
1149+
}
1150+
else
1151+
{
1152+
cap->count1 = mouse_vert_step;
1153+
}
1154+
cap->count0 = cap->count1;
1155+
nv_scroll_line(cap);
1156+
}
1157+
1158+
#ifdef FEAT_PROP_POPUP
1159+
if (WIN_IS_POPUP(curwin))
1160+
popup_set_firstline(curwin);
1161+
#endif
1162+
}
1163+
else
1164+
{
1165+
// Horizontal scrolling
1166+
long step = (mouse_hor_step < 0 || shift_or_ctrl)
1167+
? curwin->w_width : mouse_hor_step;
1168+
long leftcol = curwin->w_leftcol
1169+
+ (cap->arg == MSCR_RIGHT ? -step : step);
1170+
if (leftcol < 0)
1171+
leftcol = 0;
1172+
do_mousescroll_horiz((long_u)leftcol);
1173+
}
1174+
may_trigger_winscrolled();
1175+
}
1176+
1177+
/*
1178+
* Insert mode implementation for scrolling in direction "dir", which is
1179+
* one of the MSCR_ values.
11071180
*/
11081181
void
11091182
ins_mousescroll(int dir)
@@ -1133,18 +1206,23 @@ ins_mousescroll(int dir)
11331206
siemsg("Invalid ins_mousescroll() argument: %d", dir);
11341207
}
11351208

1136-
win_T *wp = curwin;
1209+
win_T *old_curwin = curwin;
11371210
if (mouse_row >= 0 && mouse_col >= 0)
11381211
{
11391212
// Find the window at the mouse pointer coordinates.
1213+
// NOTE: Must restore "curwin" to "old_curwin" before returning!
11401214
int row = mouse_row;
11411215
int col = mouse_col;
1142-
wp = mouse_find_win(&row, &col, FIND_POPUP);
1143-
if (wp == NULL)
1216+
curwin = mouse_find_win(&row, &col, FIND_POPUP);
1217+
if (curwin == NULL)
1218+
{
1219+
curwin = old_curwin;
11441220
return;
1221+
}
1222+
curbuf = curwin->w_buffer;
11451223
}
11461224

1147-
if (wp == curwin)
1225+
if (curwin == old_curwin)
11481226
{
11491227
// Don't scroll the current window if the popup menu is visible.
11501228
if (pum_visible())
@@ -1153,17 +1231,23 @@ ins_mousescroll(int dir)
11531231
undisplay_dollar();
11541232
}
11551233

1156-
linenr_T orig_topline = wp->w_topline;
1157-
colnr_T orig_leftcol = wp->w_leftcol;
1234+
linenr_T orig_topline = curwin->w_topline;
1235+
colnr_T orig_leftcol = curwin->w_leftcol;
11581236
pos_T orig_cursor = curwin->w_cursor;
11591237

1160-
// The scrolling works almost the same way as in Normal mode.
1161-
nv_mousescroll(&cap);
1238+
// Call the common mouse scroll function shared with other modes.
1239+
do_mousescroll(&cap);
1240+
1241+
int did_scroll = (orig_topline != curwin->w_topline
1242+
|| orig_leftcol != curwin->w_leftcol);
1243+
1244+
curwin->w_redr_status = TRUE;
1245+
curwin = old_curwin;
1246+
curbuf = curwin->w_buffer;
11621247

11631248
// If the window actually scrolled and the popup menu may overlay the
11641249
// window, need to redraw it.
1165-
if ((orig_topline != wp->w_topline || orig_leftcol != wp->w_leftcol)
1166-
&& pum_visible())
1250+
if (did_scroll && pum_visible())
11671251
{
11681252
// TODO: Would be more efficient to only redraw the windows that are
11691253
// overlapped by the popup menu.
@@ -2094,14 +2178,8 @@ do_mousescroll_horiz(long_u leftcol)
20942178
}
20952179

20962180
/*
2097-
* Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or
2098-
* mouse_hor_step, depending on the scroll direction), or one page when Shift
2099-
* or Ctrl is used.
2100-
* Direction is indicated by "cap->arg":
2101-
* K_MOUSEUP - MSCR_UP
2102-
* K_MOUSEDOWN - MSCR_DOWN
2103-
* K_MOUSELEFT - MSCR_LEFT
2104-
* K_MOUSERIGHT - MSCR_RIGHT
2181+
* Normal and Visual modes implementation for scrolling in direction
2182+
* "cap->arg", which is one of the MSCR_ values.
21052183
*/
21062184
void
21072185
nv_mousescroll(cmdarg_T *cap)
@@ -2111,85 +2189,35 @@ nv_mousescroll(cmdarg_T *cap)
21112189
if (mouse_row >= 0 && mouse_col >= 0)
21122190
{
21132191
// Find the window at the mouse pointer coordinates.
2192+
// NOTE: Must restore "curwin" to "old_curwin" before returning!
21142193
int row = mouse_row;
21152194
int col = mouse_col;
2116-
win_T *wp = mouse_find_win(&row, &col, FIND_POPUP);
2117-
if (wp == NULL)
2195+
curwin = mouse_find_win(&row, &col, FIND_POPUP);
2196+
if (curwin == NULL)
2197+
{
2198+
curwin = old_curwin;
21182199
return;
2200+
}
2201+
21192202
#ifdef FEAT_PROP_POPUP
2120-
if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar)
2203+
if (WIN_IS_POPUP(curwin) && !curwin->w_has_scrollbar)
2204+
{
21212205
// cannot scroll this popup window
2206+
curwin = old_curwin;
21222207
return;
2208+
}
21232209
#endif
2124-
// NOTE: Must restore "curwin" to "old_curwin" before returning!
2125-
curwin = wp;
21262210
curbuf = curwin->w_buffer;
21272211
}
21282212

2129-
int shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL);
2130-
2131-
#ifdef FEAT_TERMINAL
2132-
if (term_use_loop())
2133-
// This window is a terminal window, send the mouse event there.
2134-
// Set "typed" to FALSE to avoid an endless loop.
2135-
send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
2136-
else
2137-
#endif
2138-
if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
2139-
{
2140-
// Vertical scrolling
2141-
if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl))
2142-
{
2143-
// whole page up or down
2144-
onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L);
2145-
}
2146-
else
2147-
{
2148-
if (mouse_vert_step < 0 || shift_or_ctrl)
2149-
{
2150-
// whole page up or down
2151-
cap->count1 = (long)(curwin->w_botline - curwin->w_topline);
2152-
}
2153-
// Don't scroll more than half the window height.
2154-
else if (curwin->w_height < mouse_vert_step * 2)
2155-
{
2156-
cap->count1 = curwin->w_height / 2;
2157-
if (cap->count1 == 0)
2158-
cap->count1 = 1;
2159-
}
2160-
else
2161-
{
2162-
cap->count1 = mouse_vert_step;
2163-
}
2164-
cap->count0 = cap->count1;
2165-
nv_scroll_line(cap);
2166-
}
2167-
2168-
#ifdef FEAT_PROP_POPUP
2169-
if (WIN_IS_POPUP(curwin))
2170-
popup_set_firstline(curwin);
2171-
#endif
2172-
}
2173-
else
2174-
{
2175-
// Horizontal scrolling
2176-
long step = (mouse_hor_step < 0 || shift_or_ctrl)
2177-
? curwin->w_width : mouse_hor_step;
2178-
long leftcol = curwin->w_leftcol
2179-
+ (cap->arg == MSCR_RIGHT ? -step : step);
2180-
if (leftcol < 0)
2181-
leftcol = 0;
2182-
do_mousescroll_horiz((long_u)leftcol);
2183-
}
2213+
// Call the common mouse scroll function shared with other modes.
2214+
do_mousescroll(cap);
21842215

21852216
#ifdef FEAT_SYN_HL
21862217
if (curwin != old_curwin && curwin->w_p_cul)
21872218
redraw_for_cursorline(curwin);
21882219
#endif
2189-
may_trigger_winscrolled();
2190-
21912220
curwin->w_redr_status = TRUE;
2192-
21932221
curwin = old_curwin;
21942222
curbuf = curwin->w_buffer;
21952223
}

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ static char *(features[]) =
695695

696696
static int included_patches[] =
697697
{ /* Add new patch number below this line */
698+
/**/
699+
906,
698700
/**/
699701
905,
700702
/**/

0 commit comments

Comments
 (0)