Skip to content

Commit

Permalink
Prevent flickering in curses
Browse files Browse the repository at this point in the history
Reading from curs_refresh(3X) from curses, calling doupdate() repeatedly
will cause 'several bursts of output to the screen'. wnoutrefresh() has
the smarts to only copy the changed lines to the copied virtual screen,
but doupdate() does not.

There have been several bug reports related to flickering but all seems
to be inconsistenly reproducible due to different terminal buffering
behavior. See #1032, #327

Unfortunately, when I am using a slow display, I still notice
flickering, so this commit changes the routines for opening new windows
and splitting windows to wait until the last change is finished before
calling doupdate().
  • Loading branch information
mujo-hash authored and rnpnr committed Aug 1, 2023
1 parent 32e20a2 commit d1f2c27
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ui-terminal-curses.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ static void ui_curses_blit(UiTerm *tui) {
}
}
wnoutrefresh(stdscr);
doupdate();
if (tui->doupdate)
doupdate();
}

static void ui_curses_clear(UiTerm *tui) {
Expand Down
8 changes: 8 additions & 0 deletions ui-terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef struct {
CellStyle *styles; /* each window has UI_STYLE_MAX different style definitions */
size_t cells_size; /* #bytes allocated for 2D grid (grows only) */
Cell *cells; /* 2D grid of cells, at least as large as current terminal size */
bool doupdate; /* Whether to update the screen after refreshing contents */
} UiTerm;

struct UiTermWin {
Expand Down Expand Up @@ -347,6 +348,11 @@ static void ui_arrange(Ui *ui, enum UiLayout layout) {
}
}

static void ui_doupdates(Ui *ui, bool doupdate) {
UiTerm *tui = (UiTerm*)ui;
tui->doupdate = doupdate;
}

static void ui_draw(Ui *ui) {
debug("ui-draw\n");
UiTerm *tui = (UiTerm*)ui;
Expand Down Expand Up @@ -684,6 +690,7 @@ Ui *ui_term_new(void) {
}
tui->styles_size = styles_size;
tui->styles = styles;
tui->doupdate = true;
Ui *ui = (Ui*)tui;
*ui = (Ui) {
.init = ui_init,
Expand All @@ -699,6 +706,7 @@ Ui *ui_term_new(void) {
.draw = ui_draw,
.redraw = ui_redraw,
.arrange = ui_arrange,
.doupdates = ui_doupdates,
.die = ui_die,
.info = ui_info,
.info_hide = ui_info_hide,
Expand Down
1 change: 1 addition & 0 deletions ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct Ui {
void (*redraw)(Ui*);
void (*suspend)(Ui*);
void (*resume)(Ui*);
void (*doupdates)(Ui*, bool);
bool (*getkey)(Ui*, TermKeyKey*);
void (*terminal_save)(Ui*, bool fscr);
void (*terminal_restore)(Ui*);
Expand Down
8 changes: 8 additions & 0 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ bool vis_window_reload(Win *win) {
}

bool vis_window_split(Win *original) {
vis_doupdates(original->vis, false);
Win *win = window_new_file(original->vis, original->file, UI_OPTION_STATUSBAR);
if (!win)
return false;
Expand All @@ -541,6 +542,7 @@ bool vis_window_split(Win *original) {
win->file = original->file;
view_options_set(win->view, view_options_get(original->view));
view_cursor_to(win->view, view_cursor_get(original->view));
vis_doupdates(win->vis, true);
return true;
}

Expand Down Expand Up @@ -599,15 +601,21 @@ void vis_resume(Vis *vis) {
vis->ui->resume(vis->ui);
}

void vis_doupdates(Vis *vis, bool doupdate) {
vis->ui->doupdates(vis->ui, doupdate);
}

bool vis_window_new(Vis *vis, const char *filename) {
File *file = file_new(vis, filename);
if (!file)
return false;
vis_doupdates(vis, false);
Win *win = window_new_file(vis, file, UI_OPTION_STATUSBAR|UI_OPTION_SYMBOL_EOF);
if (!win) {
file_free(vis, file);
return false;
}
vis_doupdates(vis, true);

return true;
}
Expand Down
7 changes: 7 additions & 0 deletions vis.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ void vis_suspend(Vis*);
* @endrst
*/
void vis_resume(Vis*);
/**
* Set doupdate flag.
* @rst
* .. note:: Prevent flickering in curses by delaying window updates.
* @endrst
*/
void vis_doupdates(Vis*, bool);
/**
* Inform the editor core that a signal occurred.
* @return Whether the signal was handled.
Expand Down

0 comments on commit d1f2c27

Please sign in to comment.