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
|
# Configuration
|
||||||
include (CheckFunctionExists)
|
include (CheckFunctionExists)
|
||||||
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
|
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
|
||||||
CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
|
CHECK_FUNCTION_EXISTS ("resizeterm" HAVE_RESIZETERM)
|
||||||
|
|
||||||
# Project source files
|
# Project source files
|
||||||
set (project_sources ${PROJECT_NAME}.c)
|
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.
|
* 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 <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -27,9 +25,9 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <poll.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <uv.h>
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#include "termo.h"
|
#include "termo.h"
|
||||||
|
|
||||||
|
@ -45,6 +43,11 @@ struct app_context
|
||||||
{
|
{
|
||||||
termo_t *tk; ///< Termo instance
|
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
|
chtype palette[2 * 9]; ///< Attribute palette
|
||||||
|
|
||||||
uint8_t *bitmap; ///< Canvas data for drawing
|
uint8_t *bitmap; ///< Canvas data for drawing
|
||||||
|
@ -74,7 +77,14 @@ app_init (app_context_t *self)
|
||||||
memset (self, 0, sizeof *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
|
static void
|
||||||
display (const char *format, ...)
|
display (const char *format, ...)
|
||||||
|
@ -526,11 +536,74 @@ on_key (app_context_t *app, termo_key_t *key)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
winch_handler (int signum)
|
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;
|
(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
|
int
|
||||||
|
@ -542,18 +615,6 @@ main (int argc, char *argv[])
|
||||||
TERMO_CHECK_VERSION;
|
TERMO_CHECK_VERSION;
|
||||||
setlocale (LC_CTYPE, "");
|
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);
|
termo_t *tk = termo_new (STDIN_FILENO, NULL, 0);
|
||||||
if (!tk)
|
if (!tk)
|
||||||
{
|
{
|
||||||
|
@ -575,56 +636,29 @@ main (int argc, char *argv[])
|
||||||
app_init (&app);
|
app_init (&app);
|
||||||
app.tk = tk;
|
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);
|
init_palette (&app);
|
||||||
update_canvas_for_screen (&app);
|
update_canvas_for_screen (&app);
|
||||||
redraw (&app);
|
redraw (&app);
|
||||||
redraw_canvas (&app);
|
redraw_canvas (&app);
|
||||||
|
|
||||||
termo_result_t ret;
|
uv_run (loop, UV_RUN_DEFAULT);
|
||||||
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
|
|
||||||
endwin ();
|
endwin ();
|
||||||
refresh ();
|
|
||||||
|
|
||||||
update_canvas_for_screen (&app);
|
uv_loop_close (loop);
|
||||||
redraw (&app);
|
app_free (&app);
|
||||||
redraw_canvas (&app);
|
return 0;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#define PROJECT_VERSION "${project_VERSION}"
|
#define PROJECT_VERSION "${project_VERSION}"
|
||||||
#define PROJECT_URL "${project_URL}"
|
#define PROJECT_URL "${project_URL}"
|
||||||
|
|
||||||
#cmakedefine HAVE_RESIZE_TERM
|
#cmakedefine HAVE_RESIZETERM
|
||||||
|
|
||||||
#endif // ! CONFIG_H
|
#endif // ! CONFIG_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue