[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.
This commit is contained in:
Bill Currie 2020-02-27 21:01:09 +09:00
parent b4aebc120e
commit 08bf8a04e4
3 changed files with 128 additions and 4 deletions

25
tools/qwaq/event.h Normal file
View file

@ -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

View file

@ -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;

View file

@ -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}
};