--- /dev/null
+#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;
+}
--- /dev/null
+#ifndef _EVENTS_H
+#define _EVENTS_H
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkkeysyms-compat.h>
+#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 */
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkkeysyms-compat.h>
#include "config.h"
+#include "events.h"
#include "main.h"
#include "map.h"
#include "normal.h"
*/
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];
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;
}
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