From ee5f1b4cf2b82af47cc55af1334c866bf14945fa Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Fri, 24 Oct 2014 22:59:24 +0200 Subject: 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. --- CMakeLists.txt | 2 +- autistdraw.c | 158 +++++++++++++++++++++++++++++++++++---------------------- config.h.in | 2 +- 3 files changed, 98 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08ca44f..214e326 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/autistdraw.c b/autistdraw.c index f7c52de..4f1b6e4 100644 --- a/autistdraw.c +++ b/autistdraw.c @@ -17,8 +17,6 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ -// might need this for sigset_t -#define _XOPEN_SOURCE 600 #include #include @@ -27,9 +25,9 @@ #include #include -#include #include +#include #include #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 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 -winch_handler (int signum) +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; - 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 }, - }; + uv_loop_t *loop = uv_default_loop (); + loop->data = &app; - // 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); + uv_signal_init (loop, &app.winch_watcher); + uv_signal_start (&app.winch_watcher, on_winch, SIGWINCH); - // The "official" simple and flicker-prone method of resizing - // the internal buffers of curses - endwin (); - refresh (); + uv_tty_init (loop, &app.tty, STDOUT_FILENO, false); - update_canvas_for_screen (&app); - redraw (&app); - redraw_canvas (&app); - } - if (fds[0].revents & (POLLIN | POLLHUP | POLLERR)) - termo_advisereadable (tk); + uv_poll_init (loop, &app.tty_watcher, STDIN_FILENO); + uv_poll_start (&app.tty_watcher, UV_READABLE, on_tty_readable); - while ((ret = termo_getkey (tk, &key)) == TERMO_RES_KEY) - running &= on_key (&app, &key); + uv_timer_init (loop, &app.tty_timer); - nextwait = -1; - if (ret == TERMO_RES_AGAIN) - nextwait = termo_get_waittime (tk); - } + init_palette (&app); + update_canvas_for_screen (&app); + redraw (&app); + redraw_canvas (&app); + uv_run (loop, UV_RUN_DEFAULT); endwin (); - termo_destroy (tk); + + uv_loop_close (loop); + app_free (&app); + return 0; } diff --git a/config.h.in b/config.h.in index 2e0b129..27f026d 100644 --- a/config.h.in +++ b/config.h.in @@ -5,7 +5,7 @@ #define PROJECT_VERSION "${project_VERSION}" #define PROJECT_URL "${project_URL}" -#cmakedefine HAVE_RESIZE_TERM +#cmakedefine HAVE_RESIZETERM #endif // ! CONFIG_H -- cgit v1.2.3-70-g09d2