aboutsummaryrefslogtreecommitdiffstats
path: root/test-visual.c
diff options
context:
space:
mode:
Diffstat (limited to 'test-visual.c')
-rw-r--r--test-visual.c106
1 files changed, 93 insertions, 13 deletions
diff --git a/test-visual.c b/test-visual.c
index bd3a610..6e2b466 100644
--- a/test-visual.c
+++ b/test-visual.c
@@ -3,6 +3,8 @@
#include <sys/ioctl.h>
#include <assert.h>
+#include <poll.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -18,10 +20,29 @@ struct abs_axis {
};
+static volatile sig_atomic_t sigwinch_received = 0;
+static volatile sig_atomic_t sigint_received = 0;
+
+
+static void
+sigwinch_handler(int signo)
+{
+ (void) signo;
+ sigwinch_received = 1;
+}
+
+
+static void
+sigint_handler(int signo)
+{
+ (void) signo;
+ sigint_received = 1;
+}
+
+
static const char *
draw_axis(char buffer[], const struct abs_axis *axis, size_t len)
{
- /* TODO axis->value can actually be out of bounds */
char value_buf[sizeof(intmax_t) * 3 + 2];
size_t width, x, value_len;
#ifdef __GNUC__
@@ -36,7 +57,9 @@ draw_axis(char buffer[], const struct abs_axis *axis, size_t len)
value_len = (size_t)sprintf(value_buf, "%ji", axis->value);
x = axis->max_len + (width - value_len) / 2;
memcpy(&buffer[x], value_buf, value_len);
- x = (size_t)(axis->value - axis->min) * len;
+ x = (size_t)(axis->value < axis->min ? 0 : /* this actually happens */
+ axis->value > axis->max ? axis->max - axis->min :
+ axis->value - axis->min) * len;
x += (size_t)(axis->max - axis->min) / 2;
x /= (size_t)(axis->max - axis->min);
memmove(&buffer[x + sizeof("\033[m") - 1], &buffer[x], len + 1 - x);
@@ -51,35 +74,70 @@ main(int argc, char *argv[])
const struct input_absinfo *absinfo;
struct libgamepad_input_event event;
struct libgamepad_device gamepad;
- const char **button_names = NULL;
- size_t max_button_name_len = 0;
+ const char **button_names;
+ size_t max_button_name_len;
size_t len, x, y, i;
struct winsize size;
- size_t button_columns = 0;
- size_t button_rows = 0;
- size_t max_abs_axis_name_len = 0;
- struct abs_axis *abs_axes = NULL;
+ size_t button_columns;
+ size_t button_rows;
+ size_t max_abs_axis_name_len;
+ struct abs_axis *abs_axes;
char *buffer;
ssize_t saxis_len;
size_t axis_len, req_axis_len;
- size_t max_max_len = 0, max_min_len = 0;
+ size_t max_max_len, max_min_len;
ssize_t r;
+ struct pollfd pfd;
+ struct sigaction action;
if (argc != 2) {
fprintf(stderr, "Please provide the path to the subdevice as the only command line argument\n");
return 1;
}
- if (libgamepad_open_device(&gamepad, AT_FDCWD, argv[1], O_RDONLY)) {
+ if (libgamepad_open_device(&gamepad, AT_FDCWD, argv[1], O_RDONLY | O_NONBLOCK)) {
perror("libgamepad_open_device");
return 1;
}
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)) {
- perror("TIOCGWINSZ");
+ pfd.fd = gamepad.fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = sigwinch_handler;
+ if (sigaction(SIGWINCH, &action, NULL)) {
+ perror("sigaction");
+ return 1;
+ }
+
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = sigint_handler;
+ if (sigaction(SIGINT, &action, NULL)) {
+ perror("sigaction");
return 1;
}
+redraw:
+ button_names = NULL;
+ max_button_name_len = 0;
+ button_columns = 0;
+ button_rows = 0;
+ max_abs_axis_name_len = 0;
+ abs_axes = NULL;
+ max_max_len = 0;
+ max_min_len = 0;
+
+ while (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)) {
+ if (errno != EINTR) {
+ perror("TIOCGWINSZ");
+ return 1;
+ }
+ sigwinch_received = 0;
+ if (sigint_received)
+ goto out;
+ }
+
size.ws_row = size.ws_row < 1 ? 1 : size.ws_row;
size.ws_col = size.ws_col < 1 ? 1 : size.ws_col;
@@ -151,11 +209,28 @@ main(int argc, char *argv[])
fflush(stdout);
for (;;) {
- /* TODO use nonblocking; listen for window resize */
+ if (sigwinch_received) {
+ sigwinch_received = 0;
+ free(button_names);
+ free(abs_axes);
+ free(buffer);
+ goto redraw;
+ }
+ if (sigint_received)
+ break;
+
+ if (poll(&pfd, 1, -1) < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+
r = libgamepad_next_event(&gamepad, &event, 1);
if (r <= 0) {
if (!r || errno == EINTR)
continue;
+ if (errno == EAGAIN)
+ break;
perror("libgamepad_next_event");
return 1;
}
@@ -179,5 +254,10 @@ main(int argc, char *argv[])
/* TODO add relative axis */
}
+out:
+ free(buffer);
+ free(button_names);
+ free(abs_axes);
+ libgamepad_close_device(&gamepad);
return 0;
}