mirror of
https://github.com/neovim/neovim.git
synced 2025-09-16 00:08:19 +00:00
refactor(redraw): various simplifications
This commit is contained in:
@@ -97,7 +97,7 @@ typedef enum {
|
|||||||
|
|
||||||
static bool redraw_popupmenu = false;
|
static bool redraw_popupmenu = false;
|
||||||
static bool msg_grid_invalid = false;
|
static bool msg_grid_invalid = false;
|
||||||
static bool resizing = false;
|
static bool resizing_autocmd = false;
|
||||||
|
|
||||||
static char *provider_err = NULL;
|
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.
|
/// 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
|
/// 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
|
/// and Columns for positioning text etc. where the final size of the screen is
|
||||||
/// needed.
|
/// 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
|
// 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
|
// will cause this function to be called again. To break the loop, just
|
||||||
// return here.
|
// return here.
|
||||||
if (resizing) {
|
if (resizing) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
resizing = true;
|
resizing = true;
|
||||||
|
|
||||||
int retry_count = 0;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
// Allocation of the screen buffers is done only when the size changes and
|
// 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
|
// when Rows and Columns have been set and we have started doing full
|
||||||
// screen stuff.
|
// screen stuff.
|
||||||
@@ -148,24 +147,9 @@ retry:
|
|||||||
|| Columns == 0
|
|| Columns == 0
|
||||||
|| (!full_screen && default_grid.chars == NULL)) {
|
|| (!full_screen && default_grid.chars == NULL)) {
|
||||||
resizing = false;
|
resizing = false;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// We're changing the size of the screen.
|
||||||
// - Allocate new arrays for default_grid
|
// - Allocate new arrays for default_grid
|
||||||
// - Move lines from the old arrays into the new arrays, clear extra
|
// - Move lines from the old arrays into the new arrays, clear extra
|
||||||
@@ -193,26 +177,13 @@ retry:
|
|||||||
default_grid.col_offset = 0;
|
default_grid.col_offset = 0;
|
||||||
default_grid.handle = DEFAULT_GRID_HANDLE;
|
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;
|
resizing = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void screenclear(void)
|
void screenclear(void)
|
||||||
{
|
{
|
||||||
check_for_delay(false);
|
check_for_delay(false);
|
||||||
screenalloc(); // allocate screen buffers if size changed
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -281,13 +252,6 @@ void screen_resize(int width, int height)
|
|||||||
return;
|
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;
|
resizing_screen = true;
|
||||||
|
|
||||||
Rows = height;
|
Rows = height;
|
||||||
@@ -301,16 +265,54 @@ void screen_resize(int width, int height)
|
|||||||
width = Columns;
|
width = Columns;
|
||||||
p_lines = Rows;
|
p_lines = Rows;
|
||||||
p_columns = Columns;
|
p_columns = Columns;
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// 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);
|
ui_call_grid_resize(1, width, height);
|
||||||
|
|
||||||
/// The window layout used to be adjusted here, but it now happens in
|
// win_new_screensize will recompute floats position, but tell the
|
||||||
/// screenalloc() (also invoked from screenclear()). That is because the
|
// compositor to not redraw them yet
|
||||||
/// recursize "resizing_screen" check above may skip this, but not screenalloc().
|
ui_comp_set_screen_valid(false);
|
||||||
|
if (msg_grid.chars) {
|
||||||
if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) {
|
msg_grid_invalid = true;
|
||||||
screenclear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) {
|
if (starting != NO_SCREEN) {
|
||||||
maketitle();
|
maketitle();
|
||||||
|
|
||||||
@@ -320,14 +322,11 @@ void screen_resize(int width, int height)
|
|||||||
// We only redraw when it's needed:
|
// We only redraw when it's needed:
|
||||||
// - While at the more prompt or executing an external command, don't
|
// - While at the more prompt or executing an external command, don't
|
||||||
// redraw, but position the cursor.
|
// 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.
|
// - in Ex mode, don't redraw anything.
|
||||||
// - Otherwise, redraw right now, and position the cursor.
|
// - 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
|
if (State == MODE_ASKMORE || State == MODE_EXTERNCMD || State == MODE_CONFIRM
|
||||||
|| exmode_active) {
|
|| exmode_active) {
|
||||||
screenalloc();
|
|
||||||
if (msg_grid.chars) {
|
if (msg_grid.chars) {
|
||||||
msg_grid_validate();
|
msg_grid_validate();
|
||||||
}
|
}
|
||||||
@@ -378,7 +377,7 @@ int update_screen(void)
|
|||||||
// Don't do anything if the screen structures are (not yet) valid.
|
// Don't do anything if the screen structures are (not yet) valid.
|
||||||
// A VimResized autocmd can invoke redrawing in the middle of a resize,
|
// A VimResized autocmd can invoke redrawing in the middle of a resize,
|
||||||
// which would bypass the checks in screen_resize for popupmenu etc.
|
// which would bypass the checks in screen_resize for popupmenu etc.
|
||||||
if (!default_grid.chars || resizing) {
|
if (resizing_autocmd || !default_grid.chars) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,34 +386,25 @@ int update_screen(void)
|
|||||||
diff_redraw(true);
|
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
|
// Postpone the redrawing when it's not needed and when being called
|
||||||
// recursively.
|
// recursively.
|
||||||
if (!redrawing() || updating_screen) {
|
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;
|
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;
|
updating_screen = 1;
|
||||||
|
|
||||||
display_tick++; // let syntax code know we're in a next round of
|
display_tick++; // let syntax code know we're in a next round of
|
||||||
// display updating
|
// display updating
|
||||||
|
|
||||||
// Tricky: vim code can reset msg_scrolled behind our back, so need
|
// Tricky: vim code can reset msg_scrolled behind our back, so need
|
||||||
// separate bookkeeping for now.
|
// separate bookkeeping for now.
|
||||||
@@ -525,7 +515,8 @@ int update_screen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == UPD_CLEAR) { // first clear screen
|
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
|
cmdline_screen_cleared(); // clear external cmdline state
|
||||||
type = UPD_NOT_VALID;
|
type = UPD_NOT_VALID;
|
||||||
// must_redraw may be set indirectly, avoid another redraw later
|
// must_redraw may be set indirectly, avoid another redraw later
|
||||||
|
@@ -1721,13 +1721,6 @@ failed:
|
|||||||
appended_lines_mark(from, linecnt);
|
appended_lines_mark(from, linecnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we were reading from the same terminal as where messages go,
|
|
||||||
// the screen will have been messed up.
|
|
||||||
// Switch on raw mode now and clear the screen.
|
|
||||||
if (read_stdin) {
|
|
||||||
screenclear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (got_int) {
|
if (got_int) {
|
||||||
if (!(flags & READ_DUMMY)) {
|
if (!(flags & READ_DUMMY)) {
|
||||||
filemess(curbuf, sfname, _(e_interr), 0);
|
filemess(curbuf, sfname, _(e_interr), 0);
|
||||||
|
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
|
|||||||
assert(p_ch >= 0 && Rows >= p_ch && Rows - p_ch <= INT_MAX);
|
assert(p_ch >= 0 && Rows >= p_ch && Rows - p_ch <= INT_MAX);
|
||||||
cmdline_row = (int)(Rows - p_ch);
|
cmdline_row = (int)(Rows - p_ch);
|
||||||
msg_row = cmdline_row;
|
msg_row = cmdline_row;
|
||||||
screenalloc(); // allocate screen buffers
|
default_grid_alloc(); // allocate screen buffers
|
||||||
set_init_2(headless_mode);
|
set_init_2(headless_mode);
|
||||||
TIME_MSG("inits 2");
|
TIME_MSG("inits 2");
|
||||||
|
|
||||||
@@ -346,13 +346,14 @@ int main(int argc, char **argv)
|
|||||||
ui_builtin_start();
|
ui_builtin_start();
|
||||||
}
|
}
|
||||||
TIME_MSG("done waiting for UI");
|
TIME_MSG("done waiting for UI");
|
||||||
|
|
||||||
// prepare screen now, so external UIs can display messages
|
|
||||||
starting = NO_BUFFERS;
|
|
||||||
screenclear();
|
|
||||||
TIME_MSG("init screen for UI");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare screen now
|
||||||
|
starting = NO_BUFFERS;
|
||||||
|
screenclear();
|
||||||
|
win_new_screensize();
|
||||||
|
TIME_MSG("clear screen");
|
||||||
|
|
||||||
if (ui_client_channel_id) {
|
if (ui_client_channel_id) {
|
||||||
ui_client_init(ui_client_channel_id);
|
ui_client_init(ui_client_channel_id);
|
||||||
ui_client_execute(ui_client_channel_id);
|
ui_client_execute(ui_client_channel_id);
|
||||||
@@ -361,8 +362,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// Default mappings (incl. menus)
|
// Default mappings (incl. menus)
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim._init_default_mappings()"),
|
Object o = NLUA_EXEC_STATIC("return vim._init_default_mappings()",
|
||||||
(Array)ARRAY_DICT_INIT, &err);
|
(Array)ARRAY_DICT_INIT, &err);
|
||||||
assert(!ERROR_SET(&err));
|
assert(!ERROR_SET(&err));
|
||||||
api_clear_error(&err);
|
api_clear_error(&err);
|
||||||
assert(o.type == kObjectTypeNil);
|
assert(o.type == kObjectTypeNil);
|
||||||
@@ -432,10 +433,8 @@ int main(int argc, char **argv)
|
|||||||
p_ut = 1;
|
p_ut = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Read in registers, history etc, from the ShaDa file.
|
// Read in registers, history etc, from the ShaDa file.
|
||||||
// This is where v:oldfiles gets filled.
|
// This is where v:oldfiles gets filled.
|
||||||
//
|
|
||||||
if (*p_shada != NUL) {
|
if (*p_shada != NUL) {
|
||||||
shada_read_everything(NULL, false, true);
|
shada_read_everything(NULL, false, true);
|
||||||
TIME_MSG("reading ShaDa");
|
TIME_MSG("reading ShaDa");
|
||||||
@@ -474,14 +473,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
setmouse(); // may start using the mouse
|
setmouse(); // may start using the mouse
|
||||||
|
|
||||||
if (exmode_active || use_remote_ui || use_builtin_ui) {
|
redraw_later(curwin, UPD_VALID);
|
||||||
// Don't clear the screen when starting in Ex mode, or when a UI might have
|
|
||||||
// displayed messages.
|
|
||||||
redraw_later(curwin, UPD_VALID);
|
|
||||||
} else {
|
|
||||||
screenclear(); // clear screen
|
|
||||||
TIME_MSG("clearing screen");
|
|
||||||
}
|
|
||||||
|
|
||||||
no_wait_return = true;
|
no_wait_return = true;
|
||||||
|
|
||||||
|
@@ -1159,10 +1159,6 @@ void wait_return(int redraw)
|
|||||||
c = CAR; // no need for a return in ex mode
|
c = CAR; // no need for a return in ex mode
|
||||||
got_int = false;
|
got_int = false;
|
||||||
} else {
|
} else {
|
||||||
// Make sure the hit-return prompt is on screen when 'guioptions' was
|
|
||||||
// just changed.
|
|
||||||
screenalloc();
|
|
||||||
|
|
||||||
State = MODE_HITRETURN;
|
State = MODE_HITRETURN;
|
||||||
setmouse();
|
setmouse();
|
||||||
cmdline_row = msg_row;
|
cmdline_row = msg_row;
|
||||||
|
@@ -2324,6 +2324,7 @@ static void do_intro_line(long row, char *mesg, int attr)
|
|||||||
/// @param eap
|
/// @param eap
|
||||||
void ex_intro(exarg_T *eap)
|
void ex_intro(exarg_T *eap)
|
||||||
{
|
{
|
||||||
|
// TODO(bfredl): use msg_grid instead!
|
||||||
screenclear();
|
screenclear();
|
||||||
intro_message(true);
|
intro_message(true);
|
||||||
wait_return(true);
|
wait_return(true);
|
||||||
|
Reference in New Issue
Block a user