Mercurial > vim
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 /* |