Mercurial > vim
comparison src/popupwin.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 | 221d4b82bc0b |
children | 294b409ce7e3 |
comparison
equal
deleted
inserted
replaced
17054:aebfdd4e9ac5 | 17055:f4de7ccdfd8c |
---|---|
1370 tv.vval.v_number = -1; | 1370 tv.vval.v_number = -1; |
1371 popup_close_and_callback(wp, &tv); | 1371 popup_close_and_callback(wp, &tv); |
1372 } | 1372 } |
1373 } | 1373 } |
1374 | 1374 |
1375 /* | |
1376 * Update "popup_mask" if needed. | |
1377 * Also recomputes the popup size and positions. | |
1378 * Also updates "popup_visible". | |
1379 * Also marks window lines for redrawing. | |
1380 */ | |
1381 void | |
1382 may_update_popup_mask(int type) | |
1383 { | |
1384 win_T *wp; | |
1385 short *mask; | |
1386 int line, col; | |
1387 int redraw_all = FALSE; | |
1388 | |
1389 // Need to recompute when switching tabs. | |
1390 // Also recompute when the type is CLEAR or NOT_VALID, something basic | |
1391 // (such as the screen size) must have changed. | |
1392 if (popup_mask_tab != curtab || type >= NOT_VALID) | |
1393 { | |
1394 popup_mask_refresh = TRUE; | |
1395 redraw_all = TRUE; | |
1396 } | |
1397 if (!popup_mask_refresh) | |
1398 { | |
1399 // Check if any buffer has changed. | |
1400 for (wp = first_popupwin; wp != NULL; wp = wp->w_next) | |
1401 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1402 popup_mask_refresh = TRUE; | |
1403 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) | |
1404 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1405 popup_mask_refresh = TRUE; | |
1406 if (!popup_mask_refresh) | |
1407 return; | |
1408 } | |
1409 | |
1410 // Need to update the mask, something has changed. | |
1411 popup_mask_refresh = FALSE; | |
1412 popup_mask_tab = curtab; | |
1413 popup_visible = FALSE; | |
1414 | |
1415 // If redrawing everything, just update "popup_mask". | |
1416 // If redrawing only what is needed, update "popup_mask_next" and then | |
1417 // compare with "popup_mask" to see what changed. | |
1418 if (type >= SOME_VALID) | |
1419 mask = popup_mask; | |
1420 else | |
1421 mask = popup_mask_next; | |
1422 vim_memset(mask, 0, screen_Rows * screen_Columns * sizeof(short)); | |
1423 | |
1424 // Find the window with the lowest zindex that hasn't been handled yet, | |
1425 // so that the window with a higher zindex overwrites the value in | |
1426 // popup_mask. | |
1427 popup_reset_handled(); | |
1428 while ((wp = find_next_popup(TRUE)) != NULL) | |
1429 { | |
1430 popup_visible = TRUE; | |
1431 | |
1432 // Recompute the position if the text changed. | |
1433 if (redraw_all | |
1434 || wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) | |
1435 popup_adjust_position(wp); | |
1436 | |
1437 for (line = wp->w_winrow; | |
1438 line < wp->w_winrow + popup_height(wp) | |
1439 && line < screen_Rows; ++line) | |
1440 for (col = wp->w_wincol; | |
1441 col < wp->w_wincol + popup_width(wp) | |
1442 && col < screen_Columns; ++col) | |
1443 mask[line * screen_Columns + col] = wp->w_zindex; | |
1444 } | |
1445 | |
1446 // Only check which lines are to be updated if not already | |
1447 // updating all lines. | |
1448 if (mask == popup_mask_next) | |
1449 for (line = 0; line < screen_Rows; ++line) | |
1450 { | |
1451 int col_done = 0; | |
1452 | |
1453 for (col = 0; col < screen_Columns; ++col) | |
1454 { | |
1455 int off = line * screen_Columns + col; | |
1456 | |
1457 if (popup_mask[off] != popup_mask_next[off]) | |
1458 { | |
1459 popup_mask[off] = popup_mask_next[off]; | |
1460 | |
1461 if (line >= cmdline_row) | |
1462 { | |
1463 // the command line needs to be cleared if text below | |
1464 // the popup is now visible. | |
1465 if (!msg_scrolled && popup_mask_next[off] == 0) | |
1466 clear_cmdline = TRUE; | |
1467 } | |
1468 else if (col >= col_done) | |
1469 { | |
1470 linenr_T lnum; | |
1471 int line_cp = line; | |
1472 int col_cp = col; | |
1473 | |
1474 // The screen position "line" / "col" needs to be | |
1475 // redrawn. Figure out what window that is and update | |
1476 // w_redraw_top and w_redr_bot. Only needs to be done | |
1477 // once for each window line. | |
1478 wp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP); | |
1479 if (wp != NULL) | |
1480 { | |
1481 if (line_cp >= wp->w_height) | |
1482 // In (or below) status line | |
1483 wp->w_redr_status = TRUE; | |
1484 // compute the position in the buffer line from the | |
1485 // position on the screen | |
1486 else if (mouse_comp_pos(wp, &line_cp, &col_cp, | |
1487 &lnum)) | |
1488 // past bottom | |
1489 wp->w_redr_status = TRUE; | |
1490 else | |
1491 redrawWinline(wp, lnum); | |
1492 | |
1493 // This line is going to be redrawn, no need to | |
1494 // check until the right side of the window. | |
1495 col_done = wp->w_wincol + wp->w_width - 1; | |
1496 } | |
1497 } | |
1498 } | |
1499 } | |
1500 } | |
1501 } | |
1502 | |
1503 /* | |
1504 * Return a string of "len" spaces in IObuff. | |
1505 */ | |
1506 static char_u * | |
1507 get_spaces(int len) | |
1508 { | |
1509 vim_memset(IObuff, ' ', (size_t)len); | |
1510 IObuff[len] = NUL; | |
1511 return IObuff; | |
1512 } | |
1513 | |
1514 /* | |
1515 * Update popup windows. They are drawn on top of normal windows. | |
1516 * "win_update" is called for each popup window, lowest zindex first. | |
1517 */ | |
1518 void | |
1519 update_popups(void (*win_update)(win_T *wp)) | |
1520 { | |
1521 win_T *wp; | |
1522 int top_off; | |
1523 int left_off; | |
1524 int total_width; | |
1525 int total_height; | |
1526 int popup_attr; | |
1527 int border_attr[4]; | |
1528 int border_char[8]; | |
1529 char_u buf[MB_MAXBYTES]; | |
1530 int row; | |
1531 int i; | |
1532 | |
1533 // Find the window with the lowest zindex that hasn't been updated yet, | |
1534 // so that the window with a higher zindex is drawn later, thus goes on | |
1535 // top. | |
1536 popup_reset_handled(); | |
1537 while ((wp = find_next_popup(TRUE)) != NULL) | |
1538 { | |
1539 // This drawing uses the zindex of the popup window, so that it's on | |
1540 // top of the text but doesn't draw when another popup with higher | |
1541 // zindex is on top of the character. | |
1542 screen_zindex = wp->w_zindex; | |
1543 | |
1544 // adjust w_winrow and w_wincol for border and padding, since | |
1545 // win_update() doesn't handle them. | |
1546 top_off = wp->w_popup_padding[0] + wp->w_popup_border[0]; | |
1547 left_off = wp->w_popup_padding[3] + wp->w_popup_border[3]; | |
1548 wp->w_winrow += top_off; | |
1549 wp->w_wincol += left_off; | |
1550 | |
1551 // Draw the popup text. | |
1552 win_update(wp); | |
1553 | |
1554 wp->w_winrow -= top_off; | |
1555 wp->w_wincol -= left_off; | |
1556 | |
1557 total_width = wp->w_popup_border[3] + wp->w_popup_padding[3] | |
1558 + wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1]; | |
1559 total_height = wp->w_popup_border[0] + wp->w_popup_padding[0] | |
1560 + wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2]; | |
1561 popup_attr = get_wcr_attr(wp); | |
1562 | |
1563 // We can only use these line drawing characters when 'encoding' is | |
1564 // "utf-8" and 'ambiwidth' is "single". | |
1565 if (enc_utf8 && *p_ambw == 's') | |
1566 { | |
1567 border_char[0] = border_char[2] = 0x2550; | |
1568 border_char[1] = border_char[3] = 0x2551; | |
1569 border_char[4] = 0x2554; | |
1570 border_char[5] = 0x2557; | |
1571 border_char[6] = 0x255d; | |
1572 border_char[7] = 0x255a; | |
1573 } | |
1574 else | |
1575 { | |
1576 border_char[0] = border_char[2] = '-'; | |
1577 border_char[1] = border_char[3] = '|'; | |
1578 for (i = 4; i < 8; ++i) | |
1579 border_char[i] = '+'; | |
1580 } | |
1581 for (i = 0; i < 8; ++i) | |
1582 if (wp->w_border_char[i] != 0) | |
1583 border_char[i] = wp->w_border_char[i]; | |
1584 | |
1585 for (i = 0; i < 4; ++i) | |
1586 { | |
1587 border_attr[i] = popup_attr; | |
1588 if (wp->w_border_highlight[i] != NULL) | |
1589 border_attr[i] = syn_name2attr(wp->w_border_highlight[i]); | |
1590 } | |
1591 | |
1592 if (wp->w_popup_border[0] > 0) | |
1593 { | |
1594 // top border | |
1595 screen_fill(wp->w_winrow, wp->w_winrow + 1, | |
1596 wp->w_wincol, | |
1597 wp->w_wincol + total_width, | |
1598 wp->w_popup_border[3] != 0 | |
1599 ? border_char[4] : border_char[0], | |
1600 border_char[0], border_attr[0]); | |
1601 if (wp->w_popup_border[1] > 0) | |
1602 { | |
1603 buf[mb_char2bytes(border_char[5], buf)] = NUL; | |
1604 screen_puts(buf, wp->w_winrow, | |
1605 wp->w_wincol + total_width - 1, border_attr[1]); | |
1606 } | |
1607 } | |
1608 | |
1609 if (wp->w_popup_padding[0] > 0) | |
1610 { | |
1611 // top padding | |
1612 row = wp->w_winrow + wp->w_popup_border[0]; | |
1613 screen_fill(row, row + wp->w_popup_padding[0], | |
1614 wp->w_wincol + wp->w_popup_border[3], | |
1615 wp->w_wincol + total_width - wp->w_popup_border[1], | |
1616 ' ', ' ', popup_attr); | |
1617 } | |
1618 | |
1619 for (row = wp->w_winrow + wp->w_popup_border[0]; | |
1620 row < wp->w_winrow + total_height - wp->w_popup_border[2]; | |
1621 ++row) | |
1622 { | |
1623 // left border | |
1624 if (wp->w_popup_border[3] > 0) | |
1625 { | |
1626 buf[mb_char2bytes(border_char[3], buf)] = NUL; | |
1627 screen_puts(buf, row, wp->w_wincol, border_attr[3]); | |
1628 } | |
1629 // left padding | |
1630 if (wp->w_popup_padding[3] > 0) | |
1631 screen_puts(get_spaces(wp->w_popup_padding[3]), row, | |
1632 wp->w_wincol + wp->w_popup_border[3], popup_attr); | |
1633 // right border | |
1634 if (wp->w_popup_border[1] > 0) | |
1635 { | |
1636 buf[mb_char2bytes(border_char[1], buf)] = NUL; | |
1637 screen_puts(buf, row, | |
1638 wp->w_wincol + total_width - 1, border_attr[1]); | |
1639 } | |
1640 // right padding | |
1641 if (wp->w_popup_padding[1] > 0) | |
1642 screen_puts(get_spaces(wp->w_popup_padding[1]), row, | |
1643 wp->w_wincol + wp->w_popup_border[3] | |
1644 + wp->w_popup_padding[3] + wp->w_width, popup_attr); | |
1645 } | |
1646 | |
1647 if (wp->w_popup_padding[2] > 0) | |
1648 { | |
1649 // bottom padding | |
1650 row = wp->w_winrow + wp->w_popup_border[0] | |
1651 + wp->w_popup_padding[0] + wp->w_height; | |
1652 screen_fill(row, row + wp->w_popup_padding[2], | |
1653 wp->w_wincol + wp->w_popup_border[3], | |
1654 wp->w_wincol + total_width - wp->w_popup_border[1], | |
1655 ' ', ' ', popup_attr); | |
1656 } | |
1657 | |
1658 if (wp->w_popup_border[2] > 0) | |
1659 { | |
1660 // bottom border | |
1661 row = wp->w_winrow + total_height - 1; | |
1662 screen_fill(row , row + 1, | |
1663 wp->w_wincol, | |
1664 wp->w_wincol + total_width, | |
1665 wp->w_popup_border[3] != 0 | |
1666 ? border_char[7] : border_char[2], | |
1667 border_char[2], border_attr[2]); | |
1668 if (wp->w_popup_border[1] > 0) | |
1669 { | |
1670 buf[mb_char2bytes(border_char[6], buf)] = NUL; | |
1671 screen_puts(buf, row, | |
1672 wp->w_wincol + total_width - 1, border_attr[2]); | |
1673 } | |
1674 } | |
1675 | |
1676 // Back to the normal zindex. | |
1677 screen_zindex = 0; | |
1678 } | |
1679 } | |
1680 | |
1375 #endif // FEAT_TEXT_PROP | 1681 #endif // FEAT_TEXT_PROP |