aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hurst <julian.hurst92@gmail.com>2022-06-20 19:12:19 +0200
committerJulian Hurst <ark@mansus.space>2023-09-07 00:09:06 +0200
commit1ddd556f7513560ba75379265a75d871322c6222 (patch)
treece4a23565fe5b226fcdda7865ed81a48507877f7
parentcef06072173925008fb5f61762fca5c893316d11 (diff)
downloadhare-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.ha3
-rw-r--r--libtui/libtui.ha34
-rw-r--r--libtui/widget/list/list.ha2
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)?;
};