Rewrite to use libuv
Also instead of resize_term() we use resizeterm() because the former seems to cause massive glitches. Not flicker-free in urxvt anymore though.
This commit is contained in:
parent
4e1c52d798
commit
ee5f1b4cf2
|
@ -43,7 +43,7 @@ include_directories (${dependencies_INCLUDE_DIRS} ${Termo_INCLUDE_DIRS})
|
|||
# Configuration
|
||||
include (CheckFunctionExists)
|
||||
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
|
||||
CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
|
||||
CHECK_FUNCTION_EXISTS ("resizeterm" HAVE_RESIZETERM)
|
||||
|
||||
# Project source files
|
||||
set (project_sources ${PROJECT_NAME}.c)
|
||||
|
|
160
autistdraw.c
160
autistdraw.c
|
@ -17,8 +17,6 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
// <poll.h> might need this for sigset_t
|
||||
#define _XOPEN_SOURCE 600
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
@ -27,9 +25,9 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <uv.h>
|
||||
#include <curses.h>
|
||||
#include "termo.h"
|
||||
|
||||
|
@ -45,6 +43,11 @@ struct app_context
|
|||
{
|
||||
termo_t *tk; ///< Termo instance
|
||||
|
||||
uv_tty_t tty; ///< TTY
|
||||
uv_poll_t tty_watcher; ///< TTY input watcher
|
||||
uv_timer_t tty_timer; ///< TTY timeout timer
|
||||
uv_signal_t winch_watcher; ///< SIGWINCH watcher
|
||||
|
||||
chtype palette[2 * 9]; ///< Attribute palette
|
||||
|
||||
uint8_t *bitmap; ///< Canvas data for drawing
|
||||
|
@ -74,7 +77,14 @@ app_init (app_context_t *self)
|
|||
memset (self, 0, sizeof *self);
|
||||
}
|
||||
|
||||
static int g_winch_pipe[2];
|
||||
static void
|
||||
app_free (app_context_t *self)
|
||||
{
|
||||
if (self->tk)
|
||||
termo_destroy (self->tk);
|
||||
|
||||
free (self->bitmap);
|
||||
}
|
||||
|
||||
static void
|
||||
display (const char *format, ...)
|
||||
|
@ -526,11 +536,74 @@ on_key (app_context_t *app, termo_key_t *key)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
winch_handler (int signum)
|
||||
static bool
|
||||
xstrtoul (unsigned long *out, const char *s, int base)
|
||||
{
|
||||
char *end;
|
||||
errno = 0;
|
||||
*out = strtoul (s, &end, base);
|
||||
return errno == 0 && !*end && end != s;
|
||||
}
|
||||
|
||||
static void
|
||||
on_winch (uv_signal_t *handle, int signum)
|
||||
{
|
||||
app_context_t *app = handle->loop->data;
|
||||
(void) signum;
|
||||
write (g_winch_pipe[1], "x", 1);
|
||||
|
||||
#ifdef HAVE_RESIZETERM
|
||||
int w, h;
|
||||
if (!uv_tty_get_winsize (&app->tty, &w, &h))
|
||||
{
|
||||
char *row = getenv ("LINES");
|
||||
char *col = getenv ("COLUMNS");
|
||||
unsigned long tmp;
|
||||
resizeterm (
|
||||
(row && xstrtoul (&tmp, row, 10)) ? (int) tmp : h,
|
||||
(col && xstrtoul (&tmp, col, 10)) ? (int) tmp : w);
|
||||
}
|
||||
#else // ! HAVE_RESIZETERM
|
||||
endwin ();
|
||||
refresh ();
|
||||
#endif // ! HAVE_RESIZETERM
|
||||
|
||||
update_canvas_for_screen (app);
|
||||
redraw (app);
|
||||
redraw_canvas (app);
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_timer (uv_timer_t *handle)
|
||||
{
|
||||
app_context_t *app = handle->loop->data;
|
||||
|
||||
termo_key_t key;
|
||||
if (termo_getkey_force (app->tk, &key) == TERMO_RES_KEY)
|
||||
if (!on_key (app, &key))
|
||||
uv_stop (handle->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_tty_readable (uv_poll_t *handle, int status, int events)
|
||||
{
|
||||
// Ignoring and hoping for the best
|
||||
(void) status;
|
||||
(void) events;
|
||||
|
||||
app_context_t *app = handle->loop->data;
|
||||
|
||||
uv_timer_stop (&app->tty_timer);
|
||||
termo_advisereadable (app->tk);
|
||||
|
||||
termo_key_t key;
|
||||
termo_result_t ret;
|
||||
while ((ret = termo_getkey (app->tk, &key)) == TERMO_RES_KEY)
|
||||
if (!on_key (app, &key))
|
||||
uv_stop (handle->loop);
|
||||
|
||||
if (ret == TERMO_RES_AGAIN)
|
||||
uv_timer_start (&app->tty_timer,
|
||||
on_key_timer, termo_get_waittime (app->tk), 0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -542,18 +615,6 @@ main (int argc, char *argv[])
|
|||
TERMO_CHECK_VERSION;
|
||||
setlocale (LC_CTYPE, "");
|
||||
|
||||
struct sigaction act;
|
||||
act.sa_handler = winch_handler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigemptyset (&act.sa_mask);
|
||||
|
||||
// Set up a self-pipe so that we can actually poll on SIGWINCH
|
||||
if (sigaction (SIGWINCH, &act, NULL) || pipe (g_winch_pipe))
|
||||
{
|
||||
fprintf (stderr, "Cannot set up signal handler\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
termo_t *tk = termo_new (STDIN_FILENO, NULL, 0);
|
||||
if (!tk)
|
||||
{
|
||||
|
@ -575,56 +636,29 @@ main (int argc, char *argv[])
|
|||
app_init (&app);
|
||||
app.tk = tk;
|
||||
|
||||
uv_loop_t *loop = uv_default_loop ();
|
||||
loop->data = &app;
|
||||
|
||||
uv_signal_init (loop, &app.winch_watcher);
|
||||
uv_signal_start (&app.winch_watcher, on_winch, SIGWINCH);
|
||||
|
||||
uv_tty_init (loop, &app.tty, STDOUT_FILENO, false);
|
||||
|
||||
uv_poll_init (loop, &app.tty_watcher, STDIN_FILENO);
|
||||
uv_poll_start (&app.tty_watcher, UV_READABLE, on_tty_readable);
|
||||
|
||||
uv_timer_init (loop, &app.tty_timer);
|
||||
|
||||
init_palette (&app);
|
||||
update_canvas_for_screen (&app);
|
||||
redraw (&app);
|
||||
redraw_canvas (&app);
|
||||
|
||||
termo_result_t ret;
|
||||
termo_key_t key;
|
||||
|
||||
// We listen for mouse/key input and terminal resize events
|
||||
struct pollfd fds[2] =
|
||||
{
|
||||
{ .fd = STDIN_FILENO, .events = POLLIN },
|
||||
{ .fd = g_winch_pipe[0], .events = POLLIN },
|
||||
};
|
||||
|
||||
// Run a simple event loop with poll()
|
||||
int nextwait = -1;
|
||||
bool running = true;
|
||||
while (running)
|
||||
{
|
||||
if (!poll (fds, 2, nextwait))
|
||||
if (termo_getkey_force (tk, &key) == TERMO_RES_KEY)
|
||||
running &= on_key (&app, &key);
|
||||
|
||||
if (fds[1].revents & (POLLIN | POLLHUP | POLLERR))
|
||||
{
|
||||
char x;
|
||||
read (fds[1].fd, &x, 1);
|
||||
|
||||
// The "official" simple and flicker-prone method of resizing
|
||||
// the internal buffers of curses
|
||||
uv_run (loop, UV_RUN_DEFAULT);
|
||||
endwin ();
|
||||
refresh ();
|
||||
|
||||
update_canvas_for_screen (&app);
|
||||
redraw (&app);
|
||||
redraw_canvas (&app);
|
||||
}
|
||||
if (fds[0].revents & (POLLIN | POLLHUP | POLLERR))
|
||||
termo_advisereadable (tk);
|
||||
|
||||
while ((ret = termo_getkey (tk, &key)) == TERMO_RES_KEY)
|
||||
running &= on_key (&app, &key);
|
||||
|
||||
nextwait = -1;
|
||||
if (ret == TERMO_RES_AGAIN)
|
||||
nextwait = termo_get_waittime (tk);
|
||||
}
|
||||
|
||||
endwin ();
|
||||
termo_destroy (tk);
|
||||
uv_loop_close (loop);
|
||||
app_free (&app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define PROJECT_VERSION "${project_VERSION}"
|
||||
#define PROJECT_URL "${project_URL}"
|
||||
|
||||
#cmakedefine HAVE_RESIZE_TERM
|
||||
#cmakedefine HAVE_RESIZETERM
|
||||
|
||||
#endif // ! CONFIG_H
|
||||
|
||||
|
|
Loading…
Reference in New Issue