Ensure all events are turned into input
authorMichael Mackus <michaelmackus@gmail.com>
Wed, 2 Nov 2016 03:12:51 +0000 (20:12 -0700)
committerMichael Mackus <michaelmackus@gmail.com>
Wed, 2 Nov 2016 03:37:30 +0000 (20:37 -0700)
src/events.c
src/events.h
src/map.c

index 92debb7..311a6ed 100644 (file)
@@ -14,7 +14,7 @@ void queue_event(GdkEventKey* e)
 {
     if (vb.mode->id != 'i') {
         /* events are only needed for input mode */
-        return;
+        return free_events();
     }
 
     GdkEventKey **newqueue = realloc(events.queue, (events.qlen + 1) * sizeof **newqueue);
@@ -39,14 +39,32 @@ void queue_event(GdkEventKey* e)
     events.qlen ++;
 }
 
+/**
+ * Free latest event & decrement qlen.
+ */
+void pop_event()
+{
+    if (events.qlen == 0) {
+        return;
+    }
+
+    free(events.queue[events.qlen - 1]);
+    events.qlen --;
+}
+
 /**
  * Process events in the queue, sending the key events to GDK.
  */
-void process_events()
+void process_events(bool is_timeout)
 {
     if (vb.mode->id != 'i') {
         /* events are only needed for input mode */
-        return;
+        return free_events();
+    }
+
+    if (!is_timeout || events.qlen > 1) {
+        /* pop last event to prevent duplicate input */
+        pop_event();
     }
 
     events.processing = true; /* signal not to map our events */
@@ -55,10 +73,9 @@ void process_events()
     {
         GdkEventKey* event = events.queue[i];
         gtk_main_do_event ((GdkEvent*) event);
-        gdk_event_free ((GdkEvent*) event);
     }
 
-    events.qlen = 0;
+    free_events();
     events.processing = false;
 }
 
@@ -75,12 +92,11 @@ bool is_processing_events()
  * Clear the event queue by resetting the length. Provided in order to
  * encapsulate the "events" global struct.
  */
-void clear_events()
+void free_events()
 {
     for (int i = 0; i < events.qlen; ++i)
     {
-        GdkEventKey* event = events.queue[events.qlen];
-        gdk_event_free ((GdkEvent*) event);
+        free(events.queue[i]);
     }
 
     events.qlen = 0;
index 32d5889..ce58c33 100644 (file)
@@ -7,8 +7,8 @@
 #include "map.h"
 
 void queue_event(GdkEventKey* e);
-void clear_events();
-void process_events();
+void free_events();
+void process_events(bool is_timeout);
 bool is_processing_events();
 
 extern VbCore vb;
index ade7e69..72734b7 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -175,20 +175,21 @@ gboolean map_keypress(GtkWidget *widget, GdkEventKey* event, gpointer data)
     vb.state.typed         = true;
     vb.state.processed_key = true;
 
+    queue_event(event);
+
     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();
+        if (!vb.state.processed_key) {
+            /* consume any unprocessed events */
+            process_events(false);
+        } else {
+            /* we're done - clear events */
+            free_events();
+        }
     }
 
     return vb.state.processed_key;
@@ -669,13 +670,8 @@ static gboolean do_timeout(gpointer data)
     /* signalize the timeout to the key handler */
     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();
-    }
+    /* consume any unprocessed events */
+    process_events(true);
 
     /* we return true to not automatically remove the resource - this is
      * required to prevent critical error when we remove the source in