Mercurial > vim
comparison src/screen.c @ 17055:f4de7ccdfd8c v8.1.1527
patch 8.1.1527: when moving popup window over the cmdline it is not redrawn
commit https://github.com/vim/vim/commit/a540f8aa3b2570f1d903b63413301ec3d48b27d5
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jun 14 19:23:57 2019 +0200
patch 8.1.1527: when moving popup window over the cmdline it is not redrawn
Problem: When moving a popup window over the command line it is not
redrawn.
Solution: Redraw the command line. Move popup redrawing code to the popupwin
file.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 14 Jun 2019 19:30:05 +0200 |
parents | 5ed4965ebc7b |
children | 7ef5283ace3c |
comparison
equal
deleted
inserted
replaced
17054:aebfdd4e9ac5 | 17055:f4de7ccdfd8c |
---|---|
119 /* | 119 /* |
120 * Buffer for one screen line (characters and attributes). | 120 * Buffer for one screen line (characters and attributes). |
121 */ | 121 */ |
122 static schar_T *current_ScreenLine; | 122 static schar_T *current_ScreenLine; |
123 | 123 |
124 #ifdef FEAT_TEXT_PROP | |
125 static void may_update_popup_mask(int type); | |
126 static void update_popups(void); | |
127 #endif | |
128 static void win_update(win_T *wp); | 124 static void win_update(win_T *wp); |
129 static void win_redr_status(win_T *wp, int ignore_pum); | 125 static void win_redr_status(win_T *wp, int ignore_pum); |
130 static void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl); | 126 static void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl); |
131 #ifdef FEAT_FOLDING | 127 #ifdef FEAT_FOLDING |
132 static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row); | 128 static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row); |
824 maybe_intro_message(); | 820 maybe_intro_message(); |
825 did_intro = TRUE; | 821 did_intro = TRUE; |
826 | 822 |
827 #ifdef FEAT_TEXT_PROP | 823 #ifdef FEAT_TEXT_PROP |
828 // Display popup windows on top of the windows. | 824 // Display popup windows on top of the windows. |
829 update_popups(); | 825 update_popups(win_update); |
830 #endif | 826 #endif |
831 | 827 |
832 #ifdef FEAT_GUI | 828 #ifdef FEAT_GUI |
833 /* Redraw the cursor and update the scrollbars when all screen updating is | 829 /* Redraw the cursor and update the scrollbars when all screen updating is |
834 * done. */ | 830 * done. */ |
999 | 995 |
1000 /* | 996 /* |
1001 * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup | 997 * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup |
1002 * window then get the "Pmenu" highlight attribute. | 998 * window then get the "Pmenu" highlight attribute. |
1003 */ | 999 */ |
1004 static int | 1000 int |
1005 get_wcr_attr(win_T *wp) | 1001 get_wcr_attr(win_T *wp) |
1006 { | 1002 { |
1007 int wcr_attr = 0; | 1003 int wcr_attr = 0; |
1008 | 1004 |
1009 if (*wp->w_p_wcr != NUL) | 1005 if (*wp->w_p_wcr != NUL) |
1012 if (bt_popup(wp->w_buffer) && wcr_attr == 0) | 1008 if (bt_popup(wp->w_buffer) && wcr_attr == 0) |
1013 wcr_attr = HL_ATTR(HLF_PNI); | 1009 wcr_attr = HL_ATTR(HLF_PNI); |
1014 #endif | 1010 #endif |
1015 return wcr_attr; | 1011 return wcr_attr; |
1016 } | 1012 } |
1017 | |
1018 #ifdef FEAT_TEXT_PROP | |
1019 | |
1020 /* | |
1021 * Update "popup_mask" if needed. | |
1022 * Also recomputes the popup size and positions. | |
1023 * Also updates "popup_visible". | |
1024 * Also marks window lines for redrawing. | |
1025 */ | |
1026 static void | |
1027 may_update_popup_mask(int type) | |
1028 { | |
1029 win_T *wp; | |
1030 short *mask; | |
1031 int line, col; | |
1032 int redraw_all = FALSE; | |
1033 | |
1034 // Need to recompute when switching tabs. | |
1035 // Also recompute when the type is CLEAR or NOT_VALID, something basic | |
1036 // (such as the screen size) must have changed. | |
1037 if (popup_mask_tab != curtab || type >= NOT_VALID) | |
1038 { | |
1039 popup_mask_refresh = TRUE; | |
1040 redraw_all = TRUE; | |
1041 } | |
1042 if (!popup_mask_refresh) | |
1043 { | |
1044 // Check if any buffer has changed. | |
1045 for (wp = first_popupwin; wp != NULL; wp = wp->w_next) | |
1046 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1047 popup_mask_refresh = TRUE; | |
1048 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) | |
1049 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1050 popup_mask_refresh = TRUE; | |
1051 if (!popup_mask_refresh) | |
1052 return; | |
1053 } | |
1054 | |
1055 // Need to update the mask, something has changed. | |
1056 popup_mask_refresh = FALSE; | |
1057 popup_mask_tab = curtab; | |
1058 popup_visible = FALSE; | |
1059 | |
1060 // If redrawing everything, just update "popup_mask". | |
1061 // If redrawing only what is needed, update "popup_mask_next" and then | |
1062 // compare with "popup_mask" to see what changed. | |
1063 if (type >= SOME_VALID) | |
1064 mask = popup_mask; | |
1065 else | |
1066 mask = popup_mask_next; | |
1067 vim_memset(mask, 0, screen_Rows * screen_Columns * sizeof(short)); | |
1068 | |
1069 // Find the window with the lowest zindex that hasn't been handled yet, | |
1070 // so that the window with a higher zindex overwrites the value in | |
1071 // popup_mask. | |
1072 popup_reset_handled(); | |
1073 while ((wp = find_next_popup(TRUE)) != NULL) | |
1074 { | |
1075 popup_visible = TRUE; | |
1076 | |
1077 // Recompute the position if the text changed. | |
1078 if (redraw_all | |
1079 || wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1080 popup_adjust_position(wp); | |
1081 | |
1082 for (line = wp->w_winrow; | |
1083 line < wp->w_winrow + popup_height(wp) | |
1084 && line < screen_Rows; ++line) | |
1085 for (col = wp->w_wincol; | |
1086 col < wp->w_wincol + popup_width(wp) | |
1087 && col < screen_Columns; ++col) | |
1088 mask[line * screen_Columns + col] = wp->w_zindex; | |
1089 } | |
1090 | |
1091 // Only check which lines are to be updated if not already | |
1092 // updating all lines. | |
1093 if (mask == popup_mask_next) | |
1094 for (line = 0; line < screen_Rows; ++line) | |
1095 { | |
1096 int col_done = 0; | |
1097 | |
1098 for (col = 0; col < screen_Columns; ++col) | |
1099 { | |
1100 int off = line * screen_Columns + col; | |
1101 | |
1102 if (popup_mask[off] != popup_mask_next[off]) | |
1103 { | |
1104 popup_mask[off] = popup_mask_next[off]; | |
1105 | |
1106 // The screen position "line" / "col" needs to be redrawn. | |
1107 // Figure out what window that is and update w_redraw_top | |
1108 // and w_redr_bot. Only needs to be done for each window | |
1109 // line. | |
1110 if (col >= col_done) | |
1111 { | |
1112 linenr_T lnum; | |
1113 int line_cp = line; | |
1114 int col_cp = col; | |
1115 | |
1116 // find the window where the row is in | |
1117 wp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP); | |
1118 if (wp != NULL) | |
1119 { | |
1120 if (line_cp >= wp->w_height) | |
1121 // In (or below) status line | |
1122 wp->w_redr_status = TRUE; | |
1123 // compute the position in the buffer line from the | |
1124 // position on the screen | |
1125 else if (mouse_comp_pos(wp, &line_cp, &col_cp, | |
1126 &lnum)) | |
1127 // past bottom | |
1128 wp->w_redr_status = TRUE; | |
1129 else | |
1130 redrawWinline(wp, lnum); | |
1131 | |
1132 // This line is going to be redrawn, no need to | |
1133 // check until the right side of the window. | |
1134 col_done = wp->w_wincol + wp->w_width - 1; | |
1135 } | |
1136 } | |
1137 } | |
1138 } | |
1139 } | |
1140 } | |
1141 | |
1142 /* | |
1143 * Return a string of "len" spaces in IObuff. | |
1144 */ | |
1145 static char_u * | |
1146 get_spaces(int len) | |
1147 { | |
1148 vim_memset(IObuff, ' ', (size_t)len); | |
1149 IObuff[len] = NUL; | |
1150 return IObuff; | |
1151 } | |
1152 | |
1153 static void | |
1154 update_popups(void) | |
1155 { | |
1156 win_T *wp; | |
1157 int top_off; | |
1158 int left_off; | |
1159 int total_width; | |
1160 int total_height; | |
1161 int popup_attr; | |
1162 int border_attr[4]; | |
1163 int border_char[8]; | |
1164 char_u buf[MB_MAXBYTES]; | |
1165 int row; | |
1166 int i; | |
1167 | |
1168 // Find the window with the lowest zindex that hasn't been updated yet, | |
1169 // so that the window with a higher zindex is drawn later, thus goes on | |
1170 // top. | |
1171 popup_reset_handled(); | |
1172 while ((wp = find_next_popup(TRUE)) != NULL) | |
1173 { | |
1174 // This drawing uses the zindex of the popup window, so that it's on | |
1175 // top of the text but doesn't draw when another popup with higher | |
1176 // zindex is on top of the character. | |
1177 screen_zindex = wp->w_zindex; | |
1178 | |
1179 // adjust w_winrow and w_wincol for border and padding, since | |
1180 // win_update() doesn't handle them. | |
1181 top_off = wp->w_popup_padding[0] + wp->w_popup_border[0]; | |
1182 left_off = wp->w_popup_padding[3] + wp->w_popup_border[3]; | |
1183 wp->w_winrow += top_off; | |
1184 wp->w_wincol += left_off; | |
1185 | |
1186 // Draw the popup text. | |
1187 win_update(wp); | |
1188 | |
1189 wp->w_winrow -= top_off; | |
1190 wp->w_wincol -= left_off; | |
1191 | |
1192 total_width = wp->w_popup_border[3] + wp->w_popup_padding[3] | |
1193 + wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1]; | |
1194 total_height = wp->w_popup_border[0] + wp->w_popup_padding[0] | |
1195 + wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2]; | |
1196 popup_attr = get_wcr_attr(wp); | |
1197 | |
1198 // We can only use these line drawing characters when 'encoding' is | |
1199 // "utf-8" and 'ambiwidth' is "single". | |
1200 if (enc_utf8 && *p_ambw == 's') | |
1201 { | |
1202 border_char[0] = border_char[2] = 0x2550; | |
1203 border_char[1] = border_char[3] = 0x2551; | |
1204 border_char[4] = 0x2554; | |
1205 border_char[5] = 0x2557; | |
1206 border_char[6] = 0x255d; | |
1207 border_char[7] = 0x255a; | |
1208 } | |
1209 else | |
1210 { | |
1211 border_char[0] = border_char[2] = '-'; | |
1212 border_char[1] = border_char[3] = '|'; | |
1213 for (i = 4; i < 8; ++i) | |
1214 border_char[i] = '+'; | |
1215 } | |
1216 for (i = 0; i < 8; ++i) | |
1217 if (wp->w_border_char[i] != 0) | |
1218 border_char[i] = wp->w_border_char[i]; | |
1219 | |
1220 for (i = 0; i < 4; ++i) | |
1221 { | |
1222 border_attr[i] = popup_attr; | |
1223 if (wp->w_border_highlight[i] != NULL) | |
1224 border_attr[i] = syn_name2attr(wp->w_border_highlight[i]); | |
1225 } | |
1226 | |
1227 if (wp->w_popup_border[0] > 0) | |
1228 { | |
1229 // top border | |
1230 screen_fill(wp->w_winrow, wp->w_winrow + 1, | |
1231 wp->w_wincol, | |
1232 wp->w_wincol + total_width, | |
1233 wp->w_popup_border[3] != 0 | |
1234 ? border_char[4] : border_char[0], | |
1235 border_char[0], border_attr[0]); | |
1236 if (wp->w_popup_border[1] > 0) | |
1237 { | |
1238 buf[mb_char2bytes(border_char[5], buf)] = NUL; | |
1239 screen_puts(buf, wp->w_winrow, | |
1240 wp->w_wincol + total_width - 1, border_attr[1]); | |
1241 } | |
1242 } | |
1243 | |
1244 if (wp->w_popup_padding[0] > 0) | |
1245 { | |
1246 // top padding | |
1247 row = wp->w_winrow + wp->w_popup_border[0]; | |
1248 screen_fill(row, row + wp->w_popup_padding[0], | |
1249 wp->w_wincol + wp->w_popup_border[3], | |
1250 wp->w_wincol + total_width - wp->w_popup_border[1], | |
1251 ' ', ' ', popup_attr); | |
1252 } | |
1253 | |
1254 for (row = wp->w_winrow + wp->w_popup_border[0]; | |
1255 row < wp->w_winrow + total_height - wp->w_popup_border[2]; | |
1256 ++row) | |
1257 { | |
1258 // left border | |
1259 if (wp->w_popup_border[3] > 0) | |
1260 { | |
1261 buf[mb_char2bytes(border_char[3], buf)] = NUL; | |
1262 screen_puts(buf, row, wp->w_wincol, border_attr[3]); | |
1263 } | |
1264 // left padding | |
1265 if (wp->w_popup_padding[3] > 0) | |
1266 screen_puts(get_spaces(wp->w_popup_padding[3]), row, | |
1267 wp->w_wincol + wp->w_popup_border[3], popup_attr); | |
1268 // right border | |
1269 if (wp->w_popup_border[1] > 0) | |
1270 { | |
1271 buf[mb_char2bytes(border_char[1], buf)] = NUL; | |
1272 screen_puts(buf, row, | |
1273 wp->w_wincol + total_width - 1, border_attr[1]); | |
1274 } | |
1275 // right padding | |
1276 if (wp->w_popup_padding[1] > 0) | |
1277 screen_puts(get_spaces(wp->w_popup_padding[1]), row, | |
1278 wp->w_wincol + wp->w_popup_border[3] | |
1279 + wp->w_popup_padding[3] + wp->w_width, popup_attr); | |
1280 } | |
1281 | |
1282 if (wp->w_popup_padding[2] > 0) | |
1283 { | |
1284 // bottom padding | |
1285 row = wp->w_winrow + wp->w_popup_border[0] | |
1286 + wp->w_popup_padding[0] + wp->w_height; | |
1287 screen_fill(row, row + wp->w_popup_padding[2], | |
1288 wp->w_wincol + wp->w_popup_border[3], | |
1289 wp->w_wincol + total_width - wp->w_popup_border[1], | |
1290 ' ', ' ', popup_attr); | |
1291 } | |
1292 | |
1293 if (wp->w_popup_border[2] > 0) | |
1294 { | |
1295 // bottom border | |
1296 row = wp->w_winrow + total_height - 1; | |
1297 screen_fill(row , row + 1, | |
1298 wp->w_wincol, | |
1299 wp->w_wincol + total_width, | |
1300 wp->w_popup_border[3] != 0 | |
1301 ? border_char[7] : border_char[2], | |
1302 border_char[2], border_attr[2]); | |
1303 if (wp->w_popup_border[1] > 0) | |
1304 { | |
1305 buf[mb_char2bytes(border_char[6], buf)] = NUL; | |
1306 screen_puts(buf, row, | |
1307 wp->w_wincol + total_width - 1, border_attr[2]); | |
1308 } | |
1309 } | |
1310 | |
1311 // Back to the normal zindex. | |
1312 screen_zindex = 0; | |
1313 } | |
1314 } | |
1315 #endif | |
1316 | 1013 |
1317 #if defined(FEAT_GUI) || defined(PROTO) | 1014 #if defined(FEAT_GUI) || defined(PROTO) |
1318 /* | 1015 /* |
1319 * Update a single window, its status line and maybe the command line msg. | 1016 * Update a single window, its status line and maybe the command line msg. |
1320 * Used for the GUI scrollbar. | 1017 * Used for the GUI scrollbar. |
1352 ) | 1049 ) |
1353 win_redr_status(wp, FALSE); | 1050 win_redr_status(wp, FALSE); |
1354 | 1051 |
1355 #ifdef FEAT_TEXT_PROP | 1052 #ifdef FEAT_TEXT_PROP |
1356 // Display popup windows on top of everything. | 1053 // Display popup windows on top of everything. |
1357 update_popups(); | 1054 update_popups(win_update); |
1358 #endif | 1055 #endif |
1359 | 1056 |
1360 update_finish(); | 1057 update_finish(); |
1361 } | 1058 } |
1362 #endif | 1059 #endif |