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