diff options
| author | Julian Hurst <julian.hurst92@gmail.com> | 2022-06-20 19:12:19 +0200 |
|---|---|---|
| committer | Julian Hurst <ark@mansus.space> | 2023-09-07 00:09:06 +0200 |
| commit | 1ddd556f7513560ba75379265a75d871322c6222 (patch) | |
| tree | ce4a23565fe5b226fcdda7865ed81a48507877f7 | |
| parent | cef06072173925008fb5f61762fca5c893316d11 (diff) | |
| download | hare-libtui-1ddd556f7513560ba75379265a75d871322c6222.tar.gz | |
Fix intermittent blanking/flickering
Clearing and printing were done in two separate write syscalls. This fix
consists in grouping them in the same write syscall by scheduling a
clear in advance. This prevents UI glitches due to the delay between
both writes.
| -rw-r--r-- | libtui/layout/layout.ha | 3 | ||||
| -rw-r--r-- | libtui/libtui.ha | 34 | ||||
| -rw-r--r-- | libtui/widget/list/list.ha | 2 |
3 files changed, 28 insertions, 11 deletions
diff --git a/libtui/layout/layout.ha b/libtui/layout/layout.ha index 8391c2f..b9d5672 100644 --- a/libtui/layout/layout.ha +++ b/libtui/layout/layout.ha @@ -19,7 +19,8 @@ export fn newlayout(widgets: *widget::widget...) layout = { // Display all the widgets contained in the given layout. export fn print(layout: layout) (void | widget::error) = { - libtui::clear(layout.widgets[0].ui); + //libtui::clear(layout.widgets[0].ui); + libtui::doclear(&layout.widgets[0].ui); for (let i = 0z; i < len(layout.widgets); i += 1) { match (layout.widgets[i].print) { case null => diff --git a/libtui/libtui.ha b/libtui/libtui.ha index 3d33680..5f862b0 100644 --- a/libtui/libtui.ha +++ b/libtui/libtui.ha @@ -19,8 +19,11 @@ export type ttyui = struct { term: tty::termios, f: io::file, listeners: []listener, + doclear: bool, }; +const CLEARESC: str = "\x1B[2J\x1B[1;1H\r"; + // Initializes the UI and returns a ttyui. export fn init() ttyui = { let f = match (tty::open()) { @@ -45,16 +48,17 @@ export fn init() ttyui = { term = term, f = f, listeners = [], + doclear = false, }; - hidecursor(ui); + hidecursor(&ui); return ui; }; -export fn hidecursor(ui: ttyui) void = { +export fn hidecursor(ui: *ttyui) void = { print(ui, "\x1B[?25l"); }; -export fn showcursor(ui: ttyui) void = { +export fn showcursor(ui: *ttyui) void = { print(ui, "\x1B[?25h"); }; @@ -65,7 +69,7 @@ export fn getwinsize(ui: ttyui) (tty::ttysize | tty::error) = { // Suspend the UI. To restore it, use [[resume]]. export fn suspend(ui: *ttyui) void = { - showcursor(*ui); + showcursor(ui); tty::termios_restore(&ui.term); }; @@ -73,13 +77,13 @@ export fn suspend(ui: *ttyui) void = { export fn resume(ui: *ttyui) void = { tty::makeraw(&ui.term)!; tty::noecho(&ui.term)!; - hidecursor(*ui); + hidecursor(ui); }; // Restores the UI state and closes and frees the resources associated with the // given ttyui. export fn finish(ui: *ttyui) void = { - showcursor(*ui); + showcursor(ui); tty::termios_restore(&ui.term); io::close(ui.f)!; free(ui.listeners); @@ -134,12 +138,24 @@ export fn addlistener(ui: *ttyui, l: listener) void = { }; // Print a string or rune to the ttyui. -export fn print(ui: ttyui, arg: (str | rune)) void = { - fmt::fprint(ui.f, arg)!; +export fn print(ui: *ttyui, arg: str) void = { + if (ui.doclear) { + fmt::fprint(ui.f, strings::concat(CLEARESC, arg))!; + ui.doclear = false; + } else { + fmt::fprint(ui.f, arg)!; + }; //fmt::fprintf(ui.f, "{}\r", arg)!; }; // Clear the ttyui. export fn clear(ui: ttyui) void = { - fmt::fprintf(ui.f, "\x1B[2J\x1B[1;1H\r")!; + fmt::fprintf(ui.f, CLEARESC)!; +}; + +// Schedule a clear on the next print to the ttyui. Used to optimize printing +// and avoid intermittent blanking/flickering by grouping the clear and print in +// the same write syscall. +export fn doclear(ui: *ttyui) void = { + ui.doclear = true; }; diff --git a/libtui/widget/list/list.ha b/libtui/widget/list/list.ha index d6eebda..3bfd499 100644 --- a/libtui/widget/list/list.ha +++ b/libtui/widget/list/list.ha @@ -149,7 +149,7 @@ export fn print(list: *widget::widget) (void | widget::error) = { // unsupported? //io::copy(list.ui.f, &st)?; let s = strio::string(&st); - libtui::print(list.widget.ui, s); + libtui::print(&list.widget.ui, s); io::close(&st)?; }; |
