From 08bf8a04e4f53750b8dfb221c8c578b8ae98611a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 21:01:09 +0900 Subject: [PATCH] [qwaq] Implement an event queue It seems to have an issue with a bogus clearing of the screen, but the basics seem to be working. --- tools/qwaq/event.h | 25 ++++++++++++ tools/qwaq/qwaq-app.r | 25 ++++++++++-- tools/qwaq/qwaq-curses.c | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 tools/qwaq/event.h diff --git a/tools/qwaq/event.h b/tools/qwaq/event.h new file mode 100644 index 000000000..a3591fdca --- /dev/null +++ b/tools/qwaq/event.h @@ -0,0 +1,25 @@ +#ifndef __qwaq_event_h +#define __qwaq_event_h + +typedef enum { + qe_idle, + qe_key, + qe_mouse, +} qwaq_etype; + +// right now, this is just a copy of ncurses MEVENT, but all int +typedef struct qwaq_mevent_s { + int id; // XXX does it matter? + int x, y, z; // z? what? + int buttons; +} qwaq_mevent_t; + +typedef struct qwaq_event_s { + qwaq_etype event_type; + union { + int key; + qwaq_mevent_t mouse; + } e; +} qwaq_event_t; + +#endif//__qwaq_event_h diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 6473ef6a8..05f07bd68 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -1,3 +1,5 @@ +#include "event.h" + typedef struct window_s *window_t; void initialize (void) = #0; @@ -6,17 +8,32 @@ void destroy_window (window_t win) = #0; void wprintf (window_t win, string fmt, ...) = #0; int wgetch (window_t win) = #0; +void process_input (void) = #0; +int get_event (qwaq_event_t *event) = #0; + int main (int argc, string *argv) { - int ch; + int ch = 0; + qwaq_event_t event = { }; initialize (); window_t win = create_window (20, 5, 50, 10); wprintf (win, "Hi there!\n"); do { - ch = wgetch (win); - if (ch) { - wprintf (win, "%d\n", ch); + process_input (); + + if (get_event (&event)) { + if (event.event_type == qe_key) { + ch = event.e.key; + wprintf (win, "key: %d\n", ch); + } else if (event.event_type == qe_mouse) { + wprintf (win, "mouse: %d %d %d %d %d\n", + event.e.mouse.id, + event.e.mouse.x, + event.e.mouse.y, + event.e.mouse.z, + event.e.mouse.buttons); + } } } while (ch != 27); return 0; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 3932298d8..a281c3327 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -40,8 +40,11 @@ #include "QF/sys.h" #include "qwaq.h" +#include "event.h" #define always_inline inline __attribute__((__always_inline__)) +#define QUEUE_SIZE 16 // must be power of 2 greater than 1 +#define QUEUE_MASK (QUEUE_SIZE - 1) typedef struct window_s { WINDOW *win; @@ -52,6 +55,9 @@ typedef struct qwaq_resources_s { int initialized; dstring_t *print_buffer; PR_RESMAP (window_t) window_map; + qwaq_event_t event_queue[QUEUE_SIZE]; + unsigned queue_head; + unsigned queue_tail; } qwaq_resources_t; static window_t * @@ -116,6 +122,8 @@ bi_initialize (progs_t *pr) keypad (stdscr, TRUE); noecho (); nonl (); + nodelay (stdscr, TRUE); + mousemask(ALL_MOUSE_EVENTS, NULL); } static void @@ -166,6 +174,78 @@ bi_wgetch (progs_t *pr) R_INT (pr) = wgetch (window->win); } +static void +add_event (qwaq_resources_t *res, qwaq_event_t *event) +{ + if (((res->queue_head - res->queue_tail) & QUEUE_MASK) != QUEUE_MASK) { + res->event_queue[res->queue_head] = *event; + res->queue_head = (res->queue_head + 1) & QUEUE_MASK; + } +} + +static int +get_event (qwaq_resources_t *res, qwaq_event_t *event) +{ + if (res->queue_head != res->queue_tail) { + if (event) { + *event = res->event_queue[res->queue_tail]; + res->queue_tail = (res->queue_tail + 1) & QUEUE_MASK; + } + return 1; + } + return 0; +} + +static void +mouse_event (qwaq_resources_t *res, MEVENT *mevent) +{ + qwaq_event_t event = {}; + event.event_type = qe_mouse; + event.e.mouse.id = mevent->id; + event.e.mouse.x = mevent->x; + event.e.mouse.y = mevent->y; + event.e.mouse.z = mevent->z; + event.e.mouse.buttons = mevent->bstate; + add_event (res, &event); +} + +static void +key_event (qwaq_resources_t *res, int key) +{ + qwaq_event_t event = {}; + event.event_type = qe_key; + event.e.key = key; + add_event (res, &event); +} + +static void +bi_process_input (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + if (Sys_CheckInput (1, -1)) { + int ch; + while ((ch = getch ()) != ERR && ch) { + fflush (stderr); + if (ch == KEY_MOUSE) { + MEVENT mevent; + getmouse (&mevent); + mouse_event (res, &mevent); + } else { + key_event (res, ch); + } + } + } +} + +static void +bi_get_event (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_event_t *event = &G_STRUCT (pr, qwaq_event_t, P_INT (pr, 0)); + + R_INT (pr) = get_event (res, event); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -184,6 +264,8 @@ static builtin_t builtins[] = { {"destroy_window", bi_destroy_window, -1}, {"wprintf", bi_wprintf, -1}, {"wgetch", bi_wgetch, -1}, + {"process_input", bi_process_input, -1}, + {"get_event", bi_get_event, -1}, {0} };