aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawscreen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/drawscreen.c')
-rw-r--r--src/nvim/drawscreen.c145
1 files changed, 68 insertions, 77 deletions
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index d2c2d7238b..7ad4193058 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -97,7 +97,7 @@ typedef enum {
static bool redraw_popupmenu = false;
static bool msg_grid_invalid = false;
-static bool resizing = false;
+static bool resizing_autocmd = false;
static char *provider_err = NULL;
@@ -115,7 +115,7 @@ void conceal_check_cursor_line(void)
}
}
-/// Resize the screen to Rows and Columns.
+/// Resize default_grid to Rows and Columns.
///
/// Allocate default_grid.chars[] and other grid arrays.
///
@@ -125,19 +125,18 @@ void conceal_check_cursor_line(void)
/// default_grid.Columns to access items in default_grid.chars[]. Use Rows
/// and Columns for positioning text etc. where the final size of the screen is
/// needed.
-void screenalloc(void)
+bool default_grid_alloc(void)
{
+ static bool resizing = false;
+
// It's possible that we produce an out-of-memory message below, which
// will cause this function to be called again. To break the loop, just
// return here.
if (resizing) {
- return;
+ return false;
}
resizing = true;
- int retry_count = 0;
-
-retry:
// Allocation of the screen buffers is done only when the size changes and
// when Rows and Columns have been set and we have started doing full
// screen stuff.
@@ -148,24 +147,9 @@ retry:
|| Columns == 0
|| (!full_screen && default_grid.chars == NULL)) {
resizing = false;
- return;
- }
-
- // Note that the window sizes are updated before reallocating the arrays,
- // thus we must not redraw here!
- RedrawingDisabled++;
-
- // win_new_screensize will recompute floats position, but tell the
- // compositor to not redraw them yet
- ui_comp_set_screen_valid(false);
- if (msg_grid.chars) {
- msg_grid_invalid = true;
+ return false;
}
- win_new_screensize(); // fit the windows in the new sized screen
-
- comp_col(); // recompute columns for shown command and ruler
-
// We're changing the size of the screen.
// - Allocate new arrays for default_grid
// - Move lines from the old arrays into the new arrays, clear extra
@@ -193,26 +177,13 @@ retry:
default_grid.col_offset = 0;
default_grid.handle = DEFAULT_GRID_HANDLE;
- must_redraw = UPD_CLEAR; // need to clear the screen later
-
- RedrawingDisabled--;
-
- // Do not apply autocommands more than 3 times to avoid an endless loop
- // in case applying autocommands always changes Rows or Columns.
- if (starting == 0 && ++retry_count <= 3) {
- apply_autocmds(EVENT_VIMRESIZED, NULL, NULL, false, curbuf);
- // In rare cases, autocommands may have altered Rows or Columns,
- // jump back to check if we need to allocate the screen again.
- goto retry;
- }
-
resizing = false;
+ return true;
}
void screenclear(void)
{
check_for_delay(false);
- screenalloc(); // allocate screen buffers if size changed
int i;
@@ -281,13 +252,6 @@ void screen_resize(int width, int height)
return;
}
- // curwin->w_buffer can be NULL when we are closing a window and the
- // buffer has already been closed and removing a scrollbar causes a resize
- // event. Don't resize then, it will happen after entering another buffer.
- if (curwin->w_buffer == NULL) {
- return;
- }
-
resizing_screen = true;
Rows = height;
@@ -301,16 +265,54 @@ void screen_resize(int width, int height)
width = Columns;
p_lines = Rows;
p_columns = Columns;
- ui_call_grid_resize(1, width, height);
- /// The window layout used to be adjusted here, but it now happens in
- /// screenalloc() (also invoked from screenclear()). That is because the
- /// recursize "resizing_screen" check above may skip this, but not screenalloc().
+ // was invoked recursively from a VimResized autocmd, handled as a loop below
+ if (resizing_autocmd) {
+ return;
+ }
+
+ int retry_count = 0;
+ resizing_autocmd = true;
+
+ bool retry_resize = true;
+ while (retry_resize) {
+ retry_resize = default_grid_alloc();
- if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) {
- screenclear();
+ // Do not apply autocommands more than 3 times to avoid an endless loop
+ // in case applying autocommands always changes Rows or Columns.
+ if (++retry_count > 3) {
+ break;
+ }
+
+ if (retry_resize) {
+ // In rare cases, autocommands may have altered Rows or Columns,
+ // retry to check if we need to allocate the screen again.
+ apply_autocmds(EVENT_VIMRESIZED, NULL, NULL, false, curbuf);
+ }
+ }
+
+ resizing_autocmd = false;
+
+ ui_call_grid_resize(1, width, height);
+
+ // win_new_screensize will recompute floats position, but tell the
+ // compositor to not redraw them yet
+ ui_comp_set_screen_valid(false);
+ if (msg_grid.chars) {
+ msg_grid_invalid = true;
}
+ // Note that the window sizes are updated before reallocating the arrays,
+ // thus we must not redraw here!
+ RedrawingDisabled++;
+
+ win_new_screensize(); // fit the windows in the new sized screen
+
+ comp_col(); // recompute columns for shown command and ruler
+
+ RedrawingDisabled--;
+ redraw_all_later(UPD_CLEAR);
+
if (starting != NO_SCREEN) {
maketitle();
@@ -320,14 +322,11 @@ void screen_resize(int width, int height)
// We only redraw when it's needed:
// - While at the more prompt or executing an external command, don't
// redraw, but position the cursor.
- // - While editing the command line, only redraw that.
+ // - While editing the command line, only redraw that. TODO: lies
// - in Ex mode, don't redraw anything.
// - Otherwise, redraw right now, and position the cursor.
- // Always need to call update_screen() or screenalloc(), to make
- // sure Rows/Columns and the size of the screen is correct!
if (State == MODE_ASKMORE || State == MODE_EXTERNCMD || State == MODE_CONFIRM
|| exmode_active) {
- screenalloc();
if (msg_grid.chars) {
msg_grid_validate();
}
@@ -378,7 +377,7 @@ int update_screen(void)
// Don't do anything if the screen structures are (not yet) valid.
// A VimResized autocmd can invoke redrawing in the middle of a resize,
// which would bypass the checks in screen_resize for popupmenu etc.
- if (!default_grid.chars || resizing) {
+ if (resizing_autocmd || !default_grid.chars) {
return FAIL;
}
@@ -387,34 +386,25 @@ int update_screen(void)
diff_redraw(true);
}
- int type = 0;
-
- if (must_redraw) {
- if (type < must_redraw) { // use maximal type
- type = must_redraw;
- }
-
- // must_redraw is reset here, so that when we run into some weird
- // reason to redraw while busy redrawing (e.g., asynchronous
- // scrolling), or update_topline() in win_update() will cause a
- // scroll, or a decoration provider requires a redraw, the screen
- // will be redrawn later or in win_update().
- must_redraw = 0;
- }
-
// Postpone the redrawing when it's not needed and when being called
// recursively.
if (!redrawing() || updating_screen) {
- must_redraw = type;
- if (type > UPD_INVERTED_ALL) {
- curwin->w_lines_valid = 0; // don't use w_lines[].wl_size now
- }
return FAIL;
}
+
+ int type = must_redraw;
+
+ // must_redraw is reset here, so that when we run into some weird
+ // reason to redraw while busy redrawing (e.g., asynchronous
+ // scrolling), or update_topline() in win_update() will cause a
+ // scroll, or a decoration provider requires a redraw, the screen
+ // will be redrawn later or in win_update().
+ must_redraw = 0;
+
updating_screen = 1;
- display_tick++; // let syntax code know we're in a next round of
- // display updating
+ display_tick++; // let syntax code know we're in a next round of
+ // display updating
// Tricky: vim code can reset msg_scrolled behind our back, so need
// separate bookkeeping for now.
@@ -525,7 +515,8 @@ int update_screen(void)
}
if (type == UPD_CLEAR) { // first clear screen
- screenclear(); // will reset clear_cmdline
+ screenclear(); // will reset clear_cmdline
+ // and set UPD_NOT_VALID for each window
cmdline_screen_cleared(); // clear external cmdline state
type = UPD_NOT_VALID;
// must_redraw may be set indirectly, avoid another redraw later