Fixed filtering of events duplicated by XIM.

Duplicate events cannot be filtered by the return value of XFilterEvent,
as that discards dead key events on some IMs (ibus), nor by its inverse,
as that discards all key events on other IMs (?).  This solution is
based on the workaround in SDL2 and takes advantage of the identical
time of the duplicate events.

Fixes #548.
Closes #554.
Closes #571.
diff --git a/src/x11_platform.h b/src/x11_platform.h
index 62ba36b..5f3b8c5 100644
--- a/src/x11_platform.h
+++ b/src/x11_platform.h
@@ -96,6 +96,12 @@
     // The last position the cursor was warped to by GLFW
     int             warpPosX, warpPosY;
 
+    // The information from the last KeyPress event
+    struct {
+        unsigned int keycode;
+        Time         time;
+    } last;
+
 } _GLFWwindowX11;
 
 
diff --git a/src/x11_window.c b/src/x11_window.c
index 95391d9..8364a7b 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -844,8 +844,13 @@
 static void processEvent(XEvent *event)
 {
     _GLFWwindow* window = NULL;
+    int keycode = 0;
     Bool filtered = False;
 
+    // HACK: Save scancode as some IMs clear the field in XFilterEvent
+    if (event->type == KeyPress || event->type == KeyRelease)
+        keycode = event->xkey.keycode;
+
     if (_glfw.x11.im)
         filtered = XFilterEvent(event, None);
 
@@ -863,28 +868,31 @@
     {
         case KeyPress:
         {
-            const int key = translateKey(event->xkey.keycode);
+            const int key = translateKey(keycode);
             const int mods = translateState(event->xkey.state);
             const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
 
             if (window->x11.ic)
             {
-                int i;
-                Status status;
-                wchar_t buffer[16];
-
-                if (filtered)
+                // HACK: Ignore duplicate key press events generated by ibus
+                //       Corresponding release events are filtered out by the
+                //       GLFW key repeat logic
+                if (window->x11.last.keycode != keycode ||
+                    window->x11.last.time != event->xkey.time)
                 {
-                    // HACK: Ignore key press events intended solely for XIM
-                    if (event->xkey.keycode)
-                    {
-                        _glfwInputKey(window,
-                                      key, event->xkey.keycode,
-                                      GLFW_PRESS, mods);
-                    }
+                    if (keycode)
+                        _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
                 }
-                else
+
+                window->x11.last.keycode = keycode;
+                window->x11.last.time = event->xkey.time;
+
+                if (!filtered)
                 {
+                    int i;
+                    Status status;
+                    wchar_t buffer[16];
+
                     const int count = XwcLookupString(window->x11.ic,
                                                       &event->xkey,
                                                       buffer, sizeof(buffer),
@@ -899,9 +907,7 @@
                 KeySym keysym;
                 XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
 
-                _glfwInputKey(window,
-                              key, event->xkey.keycode,
-                              GLFW_PRESS, mods);
+                _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
 
                 const long character = _glfwKeySym2Unicode(keysym);
                 if (character != -1)
@@ -913,7 +919,7 @@
 
         case KeyRelease:
         {
-            const int key = translateKey(event->xkey.keycode);
+            const int key = translateKey(keycode);
             const int mods = translateState(event->xkey.state);
 
             if (!_glfw.x11.xkb.detectable)
@@ -929,7 +935,7 @@
 
                     if (next.type == KeyPress &&
                         next.xkey.window == event->xkey.window &&
-                        next.xkey.keycode == event->xkey.keycode)
+                        next.xkey.keycode == keycode)
                     {
                         // HACK: Repeat events sometimes leak through due to
                         //       some sort of time drift, so add an epsilon
@@ -947,7 +953,7 @@
                 }
             }
 
-            _glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods);
+            _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
             return;
         }