From 104b6f0e34e10ad00354e3ae8ed7402d7458a609 Mon Sep 17 00:00:00 2001 From: Michael Mackus Date: Tue, 1 Nov 2016 12:34:34 -0700 Subject: [PATCH] Add rudimentary GdkEventKey queue --- src/events.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/events.h | 16 +++++++++++++ src/map.c | 29 +++++++++++++++++++++-- 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/events.c create mode 100644 src/events.h diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..a683938 --- /dev/null +++ b/src/events.c @@ -0,0 +1,66 @@ +#include "events.h" + +/* this is only to queue GDK key events, in order to later send them if the map didn't match */ +static struct { + GdkEventKey **queue; /* queue holding submitted events */ + int qlen; /* pointer to last char in queue */ + bool processing; /* whether or not events are processing */ +} events; + +/** + * Append an event into the queue. + */ +void queue_event(GdkEventKey* e) +{ + if (vb.mode->id != 'i') { + /* events are only needed for input mode */ + return; + } + + if (events.queue == NULL) { + events.queue = malloc(0); + } + + events.queue = realloc(events.queue, (events.qlen + 1) * sizeof *events.queue); + events.queue[events.qlen] = e; + events.qlen ++; +} + +/** + * Process events in the queue, sending the key events to GDK. + */ +void process_events() +{ + if (vb.mode->id != 'i') { + /* events are only needed for input mode */ + return; + } + + events.processing = true; /* signal not to map our events */ + + for (int i = 0; i < events.qlen; ++i) + { + // TODO send to gdk + } + + events.qlen = 0; + events.processing = false; +} + +/** + * Check if the events are currently processing (i.e. being sent to GDK + * unhandled). Provided in order to encapsulate the "events" global struct. + */ +bool is_processing_events() +{ + return events.processing; +} + +/** + * Clear the event queue by resetting the length. Provided in order to + * encapsulate the "events" global struct. + */ +void clear_events() +{ + events.qlen = 0; +} diff --git a/src/events.h b/src/events.h new file mode 100644 index 0000000..32d5889 --- /dev/null +++ b/src/events.h @@ -0,0 +1,16 @@ +#ifndef _EVENTS_H +#define _EVENTS_H + +#include +#include +#include "main.h" +#include "map.h" + +void queue_event(GdkEventKey* e); +void clear_events(); +void process_events(); +bool is_processing_events(); + +extern VbCore vb; + +#endif /* end of include guard: _MAP_H */ diff --git a/src/map.c b/src/map.c index c5253de..ade7e69 100644 --- a/src/map.c +++ b/src/map.c @@ -18,6 +18,7 @@ #include #include #include "config.h" +#include "events.h" #include "main.h" #include "map.h" #include "normal.h" @@ -131,6 +132,11 @@ void map_cleanup(void) */ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data) { + if (is_processing_events()) { + // events are processing, pass all keys unmodified + return false; + } + guint state = event->state; guint keyval = event->keyval; guchar string[32]; @@ -169,11 +175,22 @@ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data) vb.state.typed = true; vb.state.processed_key = true; - map_handle_keys(string, len, true); + MapState res = map_handle_keys(string, len, true); /* reset the typed flag */ vb.state.typed = false; + if (res == MAP_NOMATCH) { + /* consume any unprocessed events */ + process_events(); + } else if (res == MAP_AMBIGUOUS) { + /* queue event for later processing */ + queue_event(event); + } else if (res == MAP_DONE) { + /* we're done - clear events */ + clear_events(); + } + return vb.state.processed_key; } @@ -650,7 +667,15 @@ static char *convert_keylabel(const char *in, int inlen, int *len) static gboolean do_timeout(gpointer data) { /* signalize the timeout to the key handler */ - map_handle_keys((guchar*)"", 0, true); + MapState res = map_handle_keys((guchar*)"", 0, true); + + if (res == MAP_DONE) { + /* we're done - clear events */ + clear_events(); + } else { + /* consume any unprocessed events */ + process_events(); + } /* we return true to not automatically remove the resource - this is * required to prevent critical error when we remove the source in -- 2.20.1