UI: add "compositor" layer to merge grids for TUI use in a correct way

Initially we will use this for the popupmenu, floating windows will
follow soon

NB: writedelay + compositor is weird, we need more flexible
redraw introspection.
This commit is contained in:
Björn Linse
2018-02-03 20:11:31 +01:00
parent 894f6bee54
commit 31cbd34d97
15 changed files with 583 additions and 112 deletions

View File

@@ -19,6 +19,7 @@
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/screen.h"
#include "nvim/ui_compositor.h"
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/memory.h"
@@ -43,6 +44,8 @@ static int pum_col; // left column of pum
static bool pum_is_visible = false;
static bool pum_external = false;
static ScreenGrid pum_grid = SCREEN_GRID_INIT;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "popupmnu.c.generated.h"
#endif
@@ -317,7 +320,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
/// Redraw the popup menu, using "pum_first" and "pum_selected".
void pum_redraw(void)
{
int row = pum_row;
int row = 0;
int col;
int attr_norm = win_hl_attr(curwin, HLF_PNI);
int attr_select = win_hl_attr(curwin, HLF_PSI);
@@ -334,6 +337,37 @@ void pum_redraw(void)
int round;
int n;
int grid_width = pum_width;
int col_off = 0;
bool extra_space = false;
if (curwin->w_p_rl) {
col_off = pum_width;
if (pum_col < curwin->w_wincol + curwin->w_width - 1) {
grid_width += 1;
extra_space = true;
}
} else if (pum_col > 0) {
grid_width += 1;
col_off = 1;
extra_space = true;
}
if (pum_scrollbar > 0) {
grid_width++;
}
grid_assign_handle(&pum_grid);
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_col-col_off,
pum_height, grid_width);
if (!pum_grid.chars
|| pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) {
grid_alloc(&pum_grid, pum_height, grid_width, !moved);
ui_call_grid_resize(pum_grid.handle, pum_grid.Columns, pum_grid.Rows);
} else if (moved) {
grid_invalidate(&pum_grid);
}
// Never display more than we have
if (pum_first > pum_size - pum_height) {
pum_first = pum_size - pum_height;
@@ -356,17 +390,17 @@ void pum_redraw(void)
screen_puts_line_start(row);
// prepend a space if there is room
if (curwin->w_p_rl) {
if (pum_col < curwin->w_wincol + curwin->w_width - 1) {
grid_putchar(&default_grid, ' ', row, pum_col + 1, attr);
if (extra_space) {
if (curwin->w_p_rl) {
grid_putchar(&pum_grid, ' ', row, col_off + 1, attr);
} else {
grid_putchar(&pum_grid, ' ', row, col_off - 1, attr);
}
} else if (pum_col > 0) {
grid_putchar(&default_grid, ' ', row, pum_col - 1, attr);
}
// Display each entry, use two spaces for a Tab.
// Do this 3 times: For the main text, kind and extra info
col = pum_col;
col = col_off;
totwidth = 0;
for (round = 1; round <= 3; ++round) {
@@ -423,13 +457,13 @@ void pum_redraw(void)
size++;
}
}
grid_puts_len(&default_grid, rt, (int)STRLEN(rt), row,
grid_puts_len(&pum_grid, rt, (int)STRLEN(rt), row,
col - size + 1, attr);
xfree(rt_start);
xfree(st);
col -= width;
} else {
grid_puts_len(&default_grid, st, (int)STRLEN(st), row, col, attr);
grid_puts_len(&pum_grid, st, (int)STRLEN(st), row, col, attr);
xfree(st);
col += width;
}
@@ -440,11 +474,11 @@ void pum_redraw(void)
// Display two spaces for a Tab.
if (curwin->w_p_rl) {
grid_puts_len(&default_grid, (char_u *)" ", 2, row, col - 1,
grid_puts_len(&pum_grid, (char_u *)" ", 2, row, col - 1,
attr);
col -= 2;
} else {
grid_puts_len(&default_grid, (char_u *)" ", 2, row, col, attr);
grid_puts_len(&pum_grid, (char_u *)" ", 2, row, col, attr);
col += 2;
}
totwidth += 2;
@@ -475,37 +509,37 @@ void pum_redraw(void)
}
if (curwin->w_p_rl) {
grid_fill(&default_grid, row, row + 1, pum_col - pum_base_width - n + 1,
grid_fill(&pum_grid, row, row + 1, col_off - pum_base_width - n + 1,
col + 1, ' ', ' ', attr);
col = pum_col - pum_base_width - n + 1;
col = col_off - pum_base_width - n + 1;
} else {
grid_fill(&default_grid, row, row + 1, col,
pum_col + pum_base_width + n, ' ', ' ', attr);
col = pum_col + pum_base_width + n;
grid_fill(&pum_grid, row, row + 1, col,
col_off + pum_base_width + n, ' ', ' ', attr);
col = pum_base_width + n;
}
totwidth = pum_base_width + n;
}
if (curwin->w_p_rl) {
grid_fill(&default_grid, row, row + 1, pum_col - pum_width + 1, col + 1,
grid_fill(&pum_grid, row, row + 1, col_off - pum_width + 1, col + 1,
' ', ' ', attr);
} else {
grid_fill(&default_grid, row, row + 1, col, pum_col + pum_width, ' ', ' ',
grid_fill(&pum_grid, row, row + 1, col, col_off + pum_width, ' ', ' ',
attr);
}
if (pum_scrollbar > 0) {
if (curwin->w_p_rl) {
grid_putchar(&default_grid, ' ', row, pum_col - pum_width,
grid_putchar(&pum_grid, ' ', row, col_off - pum_width,
i >= thumb_pos && i < thumb_pos + thumb_heigth
? attr_thumb : attr_scroll);
} else {
grid_putchar(&default_grid, ' ', row, pum_col + pum_width,
grid_putchar(&pum_grid, ' ', row, col_off + pum_width,
i >= thumb_pos && i < thumb_pos + thumb_heigth
? attr_thumb : attr_scroll);
}
}
grid_puts_line_flush(&default_grid, false);
grid_puts_line_flush(&pum_grid, false);
row++;
}
}
@@ -733,9 +767,9 @@ void pum_undisplay(void)
if (pum_external) {
ui_call_popupmenu_hide();
} else {
redraw_all_later(SOME_VALID);
redraw_tabline = true;
status_redraw_all();
ui_comp_remove_grid(&pum_grid);
// TODO(bfredl): consider the possibility of keeping float grids allocated.
grid_free(&pum_grid);
}
}