comparison src/mouse.c @ 31144:388ef91ae4f5 v9.0.0906

patch 9.0.0906: mouse scroll code is not optimal Commit: https://github.com/vim/vim/commit/ff95ce0930e6db0037fe8d1fc875a6522b054582 Author: Christopher Plewright <chris@createng.com> Date: Sat Nov 19 10:47:49 2022 +0000 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)
author Bram Moolenaar <Bram@vim.org>
date Sat, 19 Nov 2022 12:00:04 +0100
parents 759b181807f7
children 7e48ddb8b079
comparison
equal deleted inserted replaced
31143:7f0cb4441fd7 31144:388ef91ae4f5
1100 // redraw status lines (in case another window became active) 1100 // redraw status lines (in case another window became active)
1101 redraw_statuslines(); 1101 redraw_statuslines();
1102 } 1102 }
1103 1103
1104 /* 1104 /*
1105 * Implementation for scrolling in Insert mode in direction "dir", which is one 1105 * Common mouse wheel scrolling, shared between Insert mode and NV modes.
1106 * of the MSCR_ values. 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.
1107 */ 1180 */
1108 void 1181 void
1109 ins_mousescroll(int dir) 1182 ins_mousescroll(int dir)
1110 { 1183 {
1111 cmdarg_T cap; 1184 cmdarg_T cap;
1131 break; 1204 break;
1132 default: 1205 default:
1133 siemsg("Invalid ins_mousescroll() argument: %d", dir); 1206 siemsg("Invalid ins_mousescroll() argument: %d", dir);
1134 } 1207 }
1135 1208
1136 win_T *wp = curwin; 1209 win_T *old_curwin = curwin;
1137 if (mouse_row >= 0 && mouse_col >= 0) 1210 if (mouse_row >= 0 && mouse_col >= 0)
1138 { 1211 {
1139 // Find the window at the mouse pointer coordinates. 1212 // Find the window at the mouse pointer coordinates.
1213 // NOTE: Must restore "curwin" to "old_curwin" before returning!
1140 int row = mouse_row; 1214 int row = mouse_row;
1141 int col = mouse_col; 1215 int col = mouse_col;
1142 wp = mouse_find_win(&row, &col, FIND_POPUP); 1216 curwin = mouse_find_win(&row, &col, FIND_POPUP);
1143 if (wp == NULL) 1217 if (curwin == NULL)
1218 {
1219 curwin = old_curwin;
1144 return; 1220 return;
1145 } 1221 }
1146 1222 curbuf = curwin->w_buffer;
1147 if (wp == curwin) 1223 }
1224
1225 if (curwin == old_curwin)
1148 { 1226 {
1149 // Don't scroll the current window if the popup menu is visible. 1227 // Don't scroll the current window if the popup menu is visible.
1150 if (pum_visible()) 1228 if (pum_visible())
1151 return; 1229 return;
1152 1230
1153 undisplay_dollar(); 1231 undisplay_dollar();
1154 } 1232 }
1155 1233
1156 linenr_T orig_topline = wp->w_topline; 1234 linenr_T orig_topline = curwin->w_topline;
1157 colnr_T orig_leftcol = wp->w_leftcol; 1235 colnr_T orig_leftcol = curwin->w_leftcol;
1158 pos_T orig_cursor = curwin->w_cursor; 1236 pos_T orig_cursor = curwin->w_cursor;
1159 1237
1160 // The scrolling works almost the same way as in Normal mode. 1238 // Call the common mouse scroll function shared with other modes.
1161 nv_mousescroll(&cap); 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;
1162 1247
1163 // If the window actually scrolled and the popup menu may overlay the 1248 // If the window actually scrolled and the popup menu may overlay the
1164 // window, need to redraw it. 1249 // window, need to redraw it.
1165 if ((orig_topline != wp->w_topline || orig_leftcol != wp->w_leftcol) 1250 if (did_scroll && pum_visible())
1166 && pum_visible())
1167 { 1251 {
1168 // TODO: Would be more efficient to only redraw the windows that are 1252 // TODO: Would be more efficient to only redraw the windows that are
1169 // overlapped by the popup menu. 1253 // overlapped by the popup menu.
1170 redraw_all_later(UPD_NOT_VALID); 1254 redraw_all_later(UPD_NOT_VALID);
1171 ins_compl_show_pum(); 1255 ins_compl_show_pum();
2092 2176
2093 return set_leftcol((colnr_T)leftcol); 2177 return set_leftcol((colnr_T)leftcol);
2094 } 2178 }
2095 2179
2096 /* 2180 /*
2097 * Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or 2181 * Normal and Visual modes implementation for scrolling in direction
2098 * mouse_hor_step, depending on the scroll direction), or one page when Shift 2182 * "cap->arg", which is one of the MSCR_ values.
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
2105 */ 2183 */
2106 void 2184 void
2107 nv_mousescroll(cmdarg_T *cap) 2185 nv_mousescroll(cmdarg_T *cap)
2108 { 2186 {
2109 win_T *old_curwin = curwin; 2187 win_T *old_curwin = curwin;
2110 2188
2111 if (mouse_row >= 0 && mouse_col >= 0) 2189 if (mouse_row >= 0 && mouse_col >= 0)
2112 { 2190 {
2113 // Find the window at the mouse pointer coordinates. 2191 // Find the window at the mouse pointer coordinates.
2192 // NOTE: Must restore "curwin" to "old_curwin" before returning!
2114 int row = mouse_row; 2193 int row = mouse_row;
2115 int col = mouse_col; 2194 int col = mouse_col;
2116 win_T *wp = mouse_find_win(&row, &col, FIND_POPUP); 2195 curwin = mouse_find_win(&row, &col, FIND_POPUP);
2117 if (wp == NULL) 2196 if (curwin == NULL)
2197 {
2198 curwin = old_curwin;
2118 return; 2199 return;
2200 }
2201
2119 #ifdef FEAT_PROP_POPUP 2202 #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 {
2121 // cannot scroll this popup window 2205 // cannot scroll this popup window
2206 curwin = old_curwin;
2122 return; 2207 return;
2123 #endif 2208 }
2124 // NOTE: Must restore "curwin" to "old_curwin" before returning! 2209 #endif
2125 curwin = wp;
2126 curbuf = curwin->w_buffer; 2210 curbuf = curwin->w_buffer;
2127 } 2211 }
2128 2212
2129 int shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL); 2213 // Call the common mouse scroll function shared with other modes.
2130 2214 do_mousescroll(cap);
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 }
2184 2215
2185 #ifdef FEAT_SYN_HL 2216 #ifdef FEAT_SYN_HL
2186 if (curwin != old_curwin && curwin->w_p_cul) 2217 if (curwin != old_curwin && curwin->w_p_cul)
2187 redraw_for_cursorline(curwin); 2218 redraw_for_cursorline(curwin);
2188 #endif 2219 #endif
2189 may_trigger_winscrolled();
2190
2191 curwin->w_redr_status = TRUE; 2220 curwin->w_redr_status = TRUE;
2192
2193 curwin = old_curwin; 2221 curwin = old_curwin;
2194 curbuf = curwin->w_buffer; 2222 curbuf = curwin->w_buffer;
2195 } 2223 }
2196 2224
2197 /* 2225 /*