diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index a8e3866c..e94e49a1 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -184,83 +184,161 @@ extern "C" {
 #define GLFW_RELEASE            0
 #define GLFW_PRESS              1
 
-/* Keyboard key definitions: 8-bit ISO-8859-1 (Latin 1) encoding is used
- * for printable keys (such as A-Z, 0-9 etc), and values above 256
- * represent special (non-printable) keys (e.g. F1, Page Up etc).
+/* Keyboard raw key codes.
+ * These key codes are inspired by the USB HID Usage Tables v1.12 (p. 53-60),
+ * but re-arranged to map to 7-bit ASCII for printable keys (function keys are
+ * put in the 256+ range).
+ * The naming of the key codes follow these rules:
+ *  - The US keyboard layout is used.
+ *  - Names of printable alpha-numeric characters are used (e.g. "A", "R",
+ *    "3", etc).
+ *  - For non-alphanumeric characters, Unicode:ish names are used (e.g.
+ *    "COMMA", "LEFT_SQUARE_BRACKET", etc). Note that some names do not
+ *    correspond to the Unicode standard (usually for brevity).
+ *  - Keys that lack a clear US mapping are named "WORLD_x".
+ *  - For non-printable keys, custom names are used (e.g. "F4",
+ *    "BACKSPACE", etc).
  */
-#define GLFW_KEY_UNKNOWN      -1
-#define GLFW_KEY_SPACE        32
-#define GLFW_KEY_SPECIAL      256
-#define GLFW_KEY_ESC          (GLFW_KEY_SPECIAL+1)
-#define GLFW_KEY_F1           (GLFW_KEY_SPECIAL+2)
-#define GLFW_KEY_F2           (GLFW_KEY_SPECIAL+3)
-#define GLFW_KEY_F3           (GLFW_KEY_SPECIAL+4)
-#define GLFW_KEY_F4           (GLFW_KEY_SPECIAL+5)
-#define GLFW_KEY_F5           (GLFW_KEY_SPECIAL+6)
-#define GLFW_KEY_F6           (GLFW_KEY_SPECIAL+7)
-#define GLFW_KEY_F7           (GLFW_KEY_SPECIAL+8)
-#define GLFW_KEY_F8           (GLFW_KEY_SPECIAL+9)
-#define GLFW_KEY_F9           (GLFW_KEY_SPECIAL+10)
-#define GLFW_KEY_F10          (GLFW_KEY_SPECIAL+11)
-#define GLFW_KEY_F11          (GLFW_KEY_SPECIAL+12)
-#define GLFW_KEY_F12          (GLFW_KEY_SPECIAL+13)
-#define GLFW_KEY_F13          (GLFW_KEY_SPECIAL+14)
-#define GLFW_KEY_F14          (GLFW_KEY_SPECIAL+15)
-#define GLFW_KEY_F15          (GLFW_KEY_SPECIAL+16)
-#define GLFW_KEY_F16          (GLFW_KEY_SPECIAL+17)
-#define GLFW_KEY_F17          (GLFW_KEY_SPECIAL+18)
-#define GLFW_KEY_F18          (GLFW_KEY_SPECIAL+19)
-#define GLFW_KEY_F19          (GLFW_KEY_SPECIAL+20)
-#define GLFW_KEY_F20          (GLFW_KEY_SPECIAL+21)
-#define GLFW_KEY_F21          (GLFW_KEY_SPECIAL+22)
-#define GLFW_KEY_F22          (GLFW_KEY_SPECIAL+23)
-#define GLFW_KEY_F23          (GLFW_KEY_SPECIAL+24)
-#define GLFW_KEY_F24          (GLFW_KEY_SPECIAL+25)
-#define GLFW_KEY_F25          (GLFW_KEY_SPECIAL+26)
-#define GLFW_KEY_UP           (GLFW_KEY_SPECIAL+27)
-#define GLFW_KEY_DOWN         (GLFW_KEY_SPECIAL+28)
-#define GLFW_KEY_LEFT         (GLFW_KEY_SPECIAL+29)
-#define GLFW_KEY_RIGHT        (GLFW_KEY_SPECIAL+30)
-#define GLFW_KEY_LSHIFT       (GLFW_KEY_SPECIAL+31)
-#define GLFW_KEY_RSHIFT       (GLFW_KEY_SPECIAL+32)
-#define GLFW_KEY_LCTRL        (GLFW_KEY_SPECIAL+33)
-#define GLFW_KEY_RCTRL        (GLFW_KEY_SPECIAL+34)
-#define GLFW_KEY_LALT         (GLFW_KEY_SPECIAL+35)
-#define GLFW_KEY_RALT         (GLFW_KEY_SPECIAL+36)
-#define GLFW_KEY_TAB          (GLFW_KEY_SPECIAL+37)
-#define GLFW_KEY_ENTER        (GLFW_KEY_SPECIAL+38)
-#define GLFW_KEY_BACKSPACE    (GLFW_KEY_SPECIAL+39)
-#define GLFW_KEY_INSERT       (GLFW_KEY_SPECIAL+40)
-#define GLFW_KEY_DEL          (GLFW_KEY_SPECIAL+41)
-#define GLFW_KEY_PAGEUP       (GLFW_KEY_SPECIAL+42)
-#define GLFW_KEY_PAGEDOWN     (GLFW_KEY_SPECIAL+43)
-#define GLFW_KEY_HOME         (GLFW_KEY_SPECIAL+44)
-#define GLFW_KEY_END          (GLFW_KEY_SPECIAL+45)
-#define GLFW_KEY_KP_0         (GLFW_KEY_SPECIAL+46)
-#define GLFW_KEY_KP_1         (GLFW_KEY_SPECIAL+47)
-#define GLFW_KEY_KP_2         (GLFW_KEY_SPECIAL+48)
-#define GLFW_KEY_KP_3         (GLFW_KEY_SPECIAL+49)
-#define GLFW_KEY_KP_4         (GLFW_KEY_SPECIAL+50)
-#define GLFW_KEY_KP_5         (GLFW_KEY_SPECIAL+51)
-#define GLFW_KEY_KP_6         (GLFW_KEY_SPECIAL+52)
-#define GLFW_KEY_KP_7         (GLFW_KEY_SPECIAL+53)
-#define GLFW_KEY_KP_8         (GLFW_KEY_SPECIAL+54)
-#define GLFW_KEY_KP_9         (GLFW_KEY_SPECIAL+55)
-#define GLFW_KEY_KP_DIVIDE    (GLFW_KEY_SPECIAL+56)
-#define GLFW_KEY_KP_MULTIPLY  (GLFW_KEY_SPECIAL+57)
-#define GLFW_KEY_KP_SUBTRACT  (GLFW_KEY_SPECIAL+58)
-#define GLFW_KEY_KP_ADD       (GLFW_KEY_SPECIAL+59)
-#define GLFW_KEY_KP_DECIMAL   (GLFW_KEY_SPECIAL+60)
-#define GLFW_KEY_KP_EQUAL     (GLFW_KEY_SPECIAL+61)
-#define GLFW_KEY_KP_ENTER     (GLFW_KEY_SPECIAL+62)
-#define GLFW_KEY_KP_NUM_LOCK  (GLFW_KEY_SPECIAL+63)
-#define GLFW_KEY_CAPS_LOCK    (GLFW_KEY_SPECIAL+64)
-#define GLFW_KEY_SCROLL_LOCK  (GLFW_KEY_SPECIAL+65)
-#define GLFW_KEY_PAUSE        (GLFW_KEY_SPECIAL+66)
-#define GLFW_KEY_LSUPER       (GLFW_KEY_SPECIAL+67)
-#define GLFW_KEY_RSUPER       (GLFW_KEY_SPECIAL+68)
-#define GLFW_KEY_MENU         (GLFW_KEY_SPECIAL+69)
-#define GLFW_KEY_LAST         GLFW_KEY_MENU
+
+/* Printable keys */
+#define GLFW_KEY_SPACE                  32
+#define GLFW_KEY_APOSTROPHE             39  /* ' */
+#define GLFW_KEY_COMMA                  44  /* , */
+#define GLFW_KEY_MINUS                  45  /* - */
+#define GLFW_KEY_PERIOD                 46  /* . */
+#define GLFW_KEY_SLASH                  47  /* / */
+#define GLFW_KEY_0                      48
+#define GLFW_KEY_1                      49
+#define GLFW_KEY_2                      50
+#define GLFW_KEY_3                      51
+#define GLFW_KEY_4                      52
+#define GLFW_KEY_5                      53
+#define GLFW_KEY_6                      54
+#define GLFW_KEY_7                      55
+#define GLFW_KEY_8                      56
+#define GLFW_KEY_9                      57
+#define GLFW_KEY_SEMICOLON              59  /* ; */
+#define GLFW_KEY_EQUAL                  61  /* = */
+#define GLFW_KEY_A                      65
+#define GLFW_KEY_B                      66
+#define GLFW_KEY_C                      67
+#define GLFW_KEY_D                      68
+#define GLFW_KEY_E                      69
+#define GLFW_KEY_F                      70
+#define GLFW_KEY_G                      71
+#define GLFW_KEY_H                      72
+#define GLFW_KEY_I                      73
+#define GLFW_KEY_J                      74
+#define GLFW_KEY_K                      75
+#define GLFW_KEY_L                      76
+#define GLFW_KEY_M                      77
+#define GLFW_KEY_N                      78
+#define GLFW_KEY_O                      79
+#define GLFW_KEY_P                      80
+#define GLFW_KEY_Q                      81
+#define GLFW_KEY_R                      82
+#define GLFW_KEY_S                      83
+#define GLFW_KEY_T                      84
+#define GLFW_KEY_U                      85
+#define GLFW_KEY_V                      86
+#define GLFW_KEY_W                      87
+#define GLFW_KEY_X                      88
+#define GLFW_KEY_Y                      89
+#define GLFW_KEY_Z                      90
+#define GLFW_KEY_LEFT_SQUARE_BRACKET    91  /* [ */
+#define GLFW_KEY_BACKSLASH              92  /* \ */
+#define GLFW_KEY_RIGHT_SQUARE_BRACKET   93  /* ] */
+#define GLFW_KEY_GRAVE_ACCENT           96  /* ` */
+#define GLFW_KEY_WORLD_1                161 /* non-US #1 */
+#define GLFW_KEY_WORLD_2                162 /* non-US #2 */
+
+/* Function keys */
+#define GLFW_KEY_ESCAPE                 256
+#define GLFW_KEY_ENTER                  257
+#define GLFW_KEY_TAB                    258
+#define GLFW_KEY_BACKSPACE              259
+#define GLFW_KEY_INSERT                 260
+#define GLFW_KEY_DELETE                 261
+#define GLFW_KEY_RIGHT                  262
+#define GLFW_KEY_LEFT                   263
+#define GLFW_KEY_DOWN                   264
+#define GLFW_KEY_UP                     265
+#define GLFW_KEY_PAGE_UP                266
+#define GLFW_KEY_PAGE_DOWN              267
+#define GLFW_KEY_HOME                   268
+#define GLFW_KEY_END                    269
+#define GLFW_KEY_CAPS_LOCK              280
+#define GLFW_KEY_SCROLL_LOCK            281
+#define GLFW_KEY_NUM_LOCK               282
+#define GLFW_KEY_PRINT_SCREEN           283
+#define GLFW_KEY_PAUSE                  284
+#define GLFW_KEY_F1                     290
+#define GLFW_KEY_F2                     291
+#define GLFW_KEY_F3                     292
+#define GLFW_KEY_F4                     293
+#define GLFW_KEY_F5                     294
+#define GLFW_KEY_F6                     295
+#define GLFW_KEY_F7                     296
+#define GLFW_KEY_F8                     297
+#define GLFW_KEY_F9                     298
+#define GLFW_KEY_F10                    299
+#define GLFW_KEY_F11                    300
+#define GLFW_KEY_F12                    301
+#define GLFW_KEY_F13                    302
+#define GLFW_KEY_F14                    303
+#define GLFW_KEY_F15                    304
+#define GLFW_KEY_F16                    305
+#define GLFW_KEY_F17                    306
+#define GLFW_KEY_F18                    307
+#define GLFW_KEY_F19                    308
+#define GLFW_KEY_F20                    309
+#define GLFW_KEY_F21                    310
+#define GLFW_KEY_F22                    311
+#define GLFW_KEY_F23                    312
+#define GLFW_KEY_F24                    313
+#define GLFW_KEY_F25                    314
+#define GLFW_KEY_KP_0                   320
+#define GLFW_KEY_KP_1                   321
+#define GLFW_KEY_KP_2                   322
+#define GLFW_KEY_KP_3                   323
+#define GLFW_KEY_KP_4                   324
+#define GLFW_KEY_KP_5                   325
+#define GLFW_KEY_KP_6                   326
+#define GLFW_KEY_KP_7                   327
+#define GLFW_KEY_KP_8                   328
+#define GLFW_KEY_KP_9                   329
+#define GLFW_KEY_KP_DECIMAL             330
+#define GLFW_KEY_KP_DIVIDE              331
+#define GLFW_KEY_KP_MULTIPLY            332
+#define GLFW_KEY_KP_SUBTRACT            333
+#define GLFW_KEY_KP_ADD                 334
+#define GLFW_KEY_KP_ENTER               335
+#define GLFW_KEY_KP_EQUAL               336
+#define GLFW_KEY_LEFT_SHIFT             340
+#define GLFW_KEY_LEFT_CONTROL           341
+#define GLFW_KEY_LEFT_ALT               342
+#define GLFW_KEY_LEFT_SUPER             343
+#define GLFW_KEY_RIGHT_SHIFT            344
+#define GLFW_KEY_RIGHT_CONTROL          345
+#define GLFW_KEY_RIGHT_ALT              346
+#define GLFW_KEY_RIGHT_SUPER            347
+#define GLFW_KEY_MENU                   348
+#define GLFW_KEY_LAST                   GLFW_KEY_MENU
+
+/* GLFW 2.x key name aliases (deprecated) */
+#define GLFW_KEY_ESC            GLFW_KEY_ESCAPE
+#define GLFW_KEY_DEL            GLFW_KEY_DELETE
+#define GLFW_KEY_PAGEUP         GLFW_KEY_PAGE_UP
+#define GLFW_KEY_PAGEDOWN       GLFW_KEY_PAGE_DOWN
+#define GLFW_KEY_KP_NUM_LOCK    GLFW_KEY_NUM_LOCK
+#define GLFW_KEY_LCTRL          GLFW_KEY_LEFT_CONTROL
+#define GLFW_KEY_LSHIFT         GLFW_KEY_LEFT_SHIFT
+#define GLFW_KEY_LALT           GLFW_KEY_LEFT_ALT
+#define GLFW_KEY_LSUPER         GLFW_KEY_LEFT_SUPER
+#define GLFW_KEY_RCTRL          GLFW_KEY_RIGHT_CONTROL
+#define GLFW_KEY_RSHIFT         GLFW_KEY_RIGHT_SHIFT
+#define GLFW_KEY_RALT           GLFW_KEY_RIGHT_ALT
+#define GLFW_KEY_RSUPER         GLFW_KEY_RIGHT_SUPER
 
 /* Mouse button definitions */
 #define GLFW_MOUSE_BUTTON_1      0
diff --git a/src/x11/platform.h b/src/x11/platform.h
index a243bffd..a370df0b 100644
--- a/src/x11/platform.h
+++ b/src/x11/platform.h
@@ -66,6 +66,9 @@
  #include <dlfcn.h>
 #endif
 
+// The Xkb extension provides improved keyboard support
+#include <X11/XKBlib.h>
+
 
 #ifndef GL_VERSION_3_0
 
@@ -173,6 +176,16 @@ typedef struct _GLFWlibraryX11
         GLboolean   gammaBroken;
     } RandR;
 
+    struct {
+        GLboolean   available;
+        int         majorOpcode;
+        int         eventBase;
+        int         errorBase;
+        int         majorVersion;
+        int         minorVersion;
+        int         keyCodeLUT[256];
+    } Xkb;
+
     // Screensaver data
     struct {
         GLboolean   changed;
diff --git a/src/x11/x11_init.c b/src/x11/x11_init.c
index ac5c3054..2f23e334 100644
--- a/src/x11/x11_init.c
+++ b/src/x11/x11_init.c
@@ -62,6 +62,107 @@ static void initLibraries(void)
 }
 
 
+//========================================================================
+// Update the key code LUT
+//========================================================================
+
+static void updateKeyCodeLUT(void)
+{
+    int i, keyCode, keyCodeGLFW;
+    char name[XkbKeyNameLength+1];
+    XkbDescPtr descr;
+
+    // Clear the LUT
+    for (i = 0; i < 256; ++i)
+    {
+        _glfwLibrary.X11.Xkb.keyCodeLUT[i] = -1;
+    }
+
+    // This functionality requires the Xkb extension
+    if (!_glfwLibrary.X11.Xkb.available)
+    {
+        return;
+    }
+
+    // Get keyboard description
+    descr = XkbGetKeyboard(_glfwLibrary.X11.display,
+                           XkbAllComponentsMask,
+                           XkbUseCoreKbd);
+
+    // Find the X11 key code -> GLFW key code mapping
+    for (keyCode = descr->min_key_code; keyCode <= descr->max_key_code; ++keyCode)
+    {
+        // Get the key name
+        for (i = 0; i < XkbKeyNameLength; ++i)
+        {
+            name[i] = descr->names->keys[keyCode].name[i];
+        }
+        name[XkbKeyNameLength] = 0;
+
+        // Map the key name to a GLFW key code. Note: We only map printable
+        // keys here, and we use the US keyboard layout.
+        if (strcmp(name, "TLDE") == 0) keyCodeGLFW = GLFW_KEY_GRAVE_ACCENT;
+        else if (strcmp(name, "AE01") == 0) keyCodeGLFW = GLFW_KEY_1;
+        else if (strcmp(name, "AE02") == 0) keyCodeGLFW = GLFW_KEY_2;
+        else if (strcmp(name, "AE03") == 0) keyCodeGLFW = GLFW_KEY_3;
+        else if (strcmp(name, "AE04") == 0) keyCodeGLFW = GLFW_KEY_4;
+        else if (strcmp(name, "AE05") == 0) keyCodeGLFW = GLFW_KEY_5;
+        else if (strcmp(name, "AE06") == 0) keyCodeGLFW = GLFW_KEY_6;
+        else if (strcmp(name, "AE07") == 0) keyCodeGLFW = GLFW_KEY_7;
+        else if (strcmp(name, "AE08") == 0) keyCodeGLFW = GLFW_KEY_8;
+        else if (strcmp(name, "AE09") == 0) keyCodeGLFW = GLFW_KEY_9;
+        else if (strcmp(name, "AE10") == 0) keyCodeGLFW = GLFW_KEY_0;
+        else if (strcmp(name, "AE11") == 0) keyCodeGLFW = GLFW_KEY_MINUS;
+        else if (strcmp(name, "AE12") == 0) keyCodeGLFW = GLFW_KEY_EQUAL;
+        else if (strcmp(name, "AD01") == 0) keyCodeGLFW = GLFW_KEY_Q;
+        else if (strcmp(name, "AD02") == 0) keyCodeGLFW = GLFW_KEY_W;
+        else if (strcmp(name, "AD03") == 0) keyCodeGLFW = GLFW_KEY_E;
+        else if (strcmp(name, "AD04") == 0) keyCodeGLFW = GLFW_KEY_R;
+        else if (strcmp(name, "AD05") == 0) keyCodeGLFW = GLFW_KEY_T;
+        else if (strcmp(name, "AD06") == 0) keyCodeGLFW = GLFW_KEY_Y;
+        else if (strcmp(name, "AD07") == 0) keyCodeGLFW = GLFW_KEY_U;
+        else if (strcmp(name, "AD08") == 0) keyCodeGLFW = GLFW_KEY_I;
+        else if (strcmp(name, "AD09") == 0) keyCodeGLFW = GLFW_KEY_O;
+        else if (strcmp(name, "AD10") == 0) keyCodeGLFW = GLFW_KEY_P;
+        else if (strcmp(name, "AD11") == 0) keyCodeGLFW = GLFW_KEY_LEFT_SQUARE_BRACKET;
+        else if (strcmp(name, "AD12") == 0) keyCodeGLFW = GLFW_KEY_RIGHT_SQUARE_BRACKET;
+        else if (strcmp(name, "AC01") == 0) keyCodeGLFW = GLFW_KEY_A;
+        else if (strcmp(name, "AC02") == 0) keyCodeGLFW = GLFW_KEY_S;
+        else if (strcmp(name, "AC03") == 0) keyCodeGLFW = GLFW_KEY_D;
+        else if (strcmp(name, "AC04") == 0) keyCodeGLFW = GLFW_KEY_F;
+        else if (strcmp(name, "AC05") == 0) keyCodeGLFW = GLFW_KEY_G;
+        else if (strcmp(name, "AC06") == 0) keyCodeGLFW = GLFW_KEY_H;
+        else if (strcmp(name, "AC07") == 0) keyCodeGLFW = GLFW_KEY_J;
+        else if (strcmp(name, "AC08") == 0) keyCodeGLFW = GLFW_KEY_K;
+        else if (strcmp(name, "AC09") == 0) keyCodeGLFW = GLFW_KEY_L;
+        else if (strcmp(name, "AC10") == 0) keyCodeGLFW = GLFW_KEY_SEMICOLON;
+        else if (strcmp(name, "AC11") == 0) keyCodeGLFW = GLFW_KEY_APOSTROPHE;
+        else if (strcmp(name, "AB01") == 0) keyCodeGLFW = GLFW_KEY_Z;
+        else if (strcmp(name, "AB02") == 0) keyCodeGLFW = GLFW_KEY_X;
+        else if (strcmp(name, "AB03") == 0) keyCodeGLFW = GLFW_KEY_C;
+        else if (strcmp(name, "AB04") == 0) keyCodeGLFW = GLFW_KEY_V;
+        else if (strcmp(name, "AB05") == 0) keyCodeGLFW = GLFW_KEY_B;
+        else if (strcmp(name, "AB06") == 0) keyCodeGLFW = GLFW_KEY_N;
+        else if (strcmp(name, "AB07") == 0) keyCodeGLFW = GLFW_KEY_M;
+        else if (strcmp(name, "AB08") == 0) keyCodeGLFW = GLFW_KEY_COMMA;
+        else if (strcmp(name, "AB09") == 0) keyCodeGLFW = GLFW_KEY_PERIOD;
+        else if (strcmp(name, "AB10") == 0) keyCodeGLFW = GLFW_KEY_SLASH;
+        else if (strcmp(name, "BKSL") == 0) keyCodeGLFW = GLFW_KEY_BACKSLASH;
+        else if (strcmp(name, "LSGT") == 0) keyCodeGLFW = GLFW_KEY_WORLD_1;
+        else keyCodeGLFW = -1;
+
+        // Update the key code LUT
+        if ((keyCode >= 0) && (keyCode < 256))
+        {
+            _glfwLibrary.X11.Xkb.keyCodeLUT[keyCode] = keyCodeGLFW;
+        }
+    }
+
+    // Free the keyboard description
+    XkbFreeKeyboard(descr, 0, True);
+}
+
+
 //========================================================================
 // Initialize X11 display and look for supported X11 extensions
 //========================================================================
@@ -126,6 +227,22 @@ static GLboolean initDisplay(void)
         return GL_FALSE;
     }
 
+    // Check if Xkb is supported on this display
+    _glfwLibrary.X11.Xkb.majorVersion = 1;
+    _glfwLibrary.X11.Xkb.minorVersion = 0;
+    _glfwLibrary.X11.Xkb.available =
+        XkbQueryExtension(_glfwLibrary.X11.display,
+                          &_glfwLibrary.X11.Xkb.majorOpcode,
+                          &_glfwLibrary.X11.Xkb.eventBase,
+                          &_glfwLibrary.X11.Xkb.errorBase,
+                          &_glfwLibrary.X11.Xkb.majorVersion,
+                          &_glfwLibrary.X11.Xkb.minorVersion);
+
+    // Update the key code LUT
+    // FIXME: We should listen to XkbMapNotify events to track changes to
+    // the keyboard mapping.
+    updateKeyCodeLUT();
+
     return GL_TRUE;
 }
 
diff --git a/src/x11/x11_window.c b/src/x11/x11_window.c
index 0b026b16..2879ecb0 100644
--- a/src/x11/x11_window.c
+++ b/src/x11/x11_window.c
@@ -35,6 +35,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
+    #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+#endif
+#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
+    #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#endif
 
 // Action for EWMH client messages
 #define _NET_WM_STATE_REMOVE        0
@@ -213,124 +219,188 @@ static GLboolean checkForEWMH(_GLFWwindow* window)
 
 static int translateKey(int keycode)
 {
-    KeySym key, key_lc, key_uc;
+    KeySym key;
 
     // Try secondary keysym, for numeric keypad keys
-    // Note: This way we always force "NumLock = ON", which at least
-    // enables GLFW users to detect numeric keypad keys
+    // Note: This way we always force "NumLock = ON", which is intentional
+    // since the returned key code should correspond to a physical
+    // location.
     key = XKeycodeToKeysym(_glfwLibrary.X11.display, keycode, 1);
     switch (key)
     {
-        // Numeric keypad
-        case XK_KP_0:         return GLFW_KEY_KP_0;
-        case XK_KP_1:         return GLFW_KEY_KP_1;
-        case XK_KP_2:         return GLFW_KEY_KP_2;
-        case XK_KP_3:         return GLFW_KEY_KP_3;
-        case XK_KP_4:         return GLFW_KEY_KP_4;
-        case XK_KP_5:         return GLFW_KEY_KP_5;
-        case XK_KP_6:         return GLFW_KEY_KP_6;
-        case XK_KP_7:         return GLFW_KEY_KP_7;
-        case XK_KP_8:         return GLFW_KEY_KP_8;
-        case XK_KP_9:         return GLFW_KEY_KP_9;
+        case XK_KP_0:           return GLFW_KEY_KP_0;
+        case XK_KP_1:           return GLFW_KEY_KP_1;
+        case XK_KP_2:           return GLFW_KEY_KP_2;
+        case XK_KP_3:           return GLFW_KEY_KP_3;
+        case XK_KP_4:           return GLFW_KEY_KP_4;
+        case XK_KP_5:           return GLFW_KEY_KP_5;
+        case XK_KP_6:           return GLFW_KEY_KP_6;
+        case XK_KP_7:           return GLFW_KEY_KP_7;
+        case XK_KP_8:           return GLFW_KEY_KP_8;
+        case XK_KP_9:           return GLFW_KEY_KP_9;
         case XK_KP_Separator:
-        case XK_KP_Decimal:   return GLFW_KEY_KP_DECIMAL;
-        case XK_KP_Equal:     return GLFW_KEY_KP_EQUAL;
-        case XK_KP_Enter:     return GLFW_KEY_KP_ENTER;
-        default:              break;
+        case XK_KP_Decimal:     return GLFW_KEY_KP_DECIMAL;
+        case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
+        case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
+        default:                break;
     }
 
-    // Now try pimary keysym
+    // Now try pimary keysym for function keys (non-printable keys). These
+    // should not be layout dependent (i.e. US layout and international
+    // layouts should give the same result).
     key = XKeycodeToKeysym(_glfwLibrary.X11.display, keycode, 0);
     switch (key)
     {
-        // Special keys (non character keys)
-        case XK_Escape:       return GLFW_KEY_ESC;
-        case XK_Tab:          return GLFW_KEY_TAB;
-        case XK_Shift_L:      return GLFW_KEY_LSHIFT;
-        case XK_Shift_R:      return GLFW_KEY_RSHIFT;
-        case XK_Control_L:    return GLFW_KEY_LCTRL;
-        case XK_Control_R:    return GLFW_KEY_RCTRL;
+        case XK_Escape:         return GLFW_KEY_ESCAPE;
+        case XK_Tab:            return GLFW_KEY_TAB;
+        case XK_Shift_L:        return GLFW_KEY_LEFT_SHIFT;
+        case XK_Shift_R:        return GLFW_KEY_RIGHT_SHIFT;
+        case XK_Control_L:      return GLFW_KEY_LEFT_CONTROL;
+        case XK_Control_R:      return GLFW_KEY_RIGHT_CONTROL;
         case XK_Meta_L:
-        case XK_Alt_L:        return GLFW_KEY_LALT;
-        case XK_Mode_switch:  // Mapped to Alt_R on many keyboards
-        case XK_Meta_R:
+        case XK_Alt_L:          return GLFW_KEY_LEFT_ALT;
+        case XK_Mode_switch: // Mapped to Alt_R on many keyboards
         case XK_ISO_Level3_Shift: // AltGr on at least some machines
-        case XK_Alt_R:        return GLFW_KEY_RALT;
-        case XK_Super_L:      return GLFW_KEY_LSUPER;
-        case XK_Super_R:      return GLFW_KEY_RSUPER;
-        case XK_Menu:         return GLFW_KEY_MENU;
-        case XK_Num_Lock:     return GLFW_KEY_KP_NUM_LOCK;
-        case XK_Caps_Lock:    return GLFW_KEY_CAPS_LOCK;
-        case XK_Scroll_Lock:  return GLFW_KEY_SCROLL_LOCK;
-        case XK_Pause:        return GLFW_KEY_PAUSE;
-        case XK_KP_Delete:
-        case XK_Delete:       return GLFW_KEY_DEL;
-        case XK_BackSpace:    return GLFW_KEY_BACKSPACE;
-        case XK_Return:       return GLFW_KEY_ENTER;
-        case XK_KP_Home:
-        case XK_Home:         return GLFW_KEY_HOME;
-        case XK_KP_End:
-        case XK_End:          return GLFW_KEY_END;
-        case XK_KP_Page_Up:
-        case XK_Page_Up:      return GLFW_KEY_PAGEUP;
-        case XK_KP_Page_Down:
-        case XK_Page_Down:    return GLFW_KEY_PAGEDOWN;
-        case XK_KP_Insert:
-        case XK_Insert:       return GLFW_KEY_INSERT;
-        case XK_KP_Left:
-        case XK_Left:         return GLFW_KEY_LEFT;
-        case XK_KP_Right:
-        case XK_Right:        return GLFW_KEY_RIGHT;
-        case XK_KP_Down:
-        case XK_Down:         return GLFW_KEY_DOWN;
-        case XK_KP_Up:
-        case XK_Up:           return GLFW_KEY_UP;
-        case XK_F1:           return GLFW_KEY_F1;
-        case XK_F2:           return GLFW_KEY_F2;
-        case XK_F3:           return GLFW_KEY_F3;
-        case XK_F4:           return GLFW_KEY_F4;
-        case XK_F5:           return GLFW_KEY_F5;
-        case XK_F6:           return GLFW_KEY_F6;
-        case XK_F7:           return GLFW_KEY_F7;
-        case XK_F8:           return GLFW_KEY_F8;
-        case XK_F9:           return GLFW_KEY_F9;
-        case XK_F10:          return GLFW_KEY_F10;
-        case XK_F11:          return GLFW_KEY_F11;
-        case XK_F12:          return GLFW_KEY_F12;
-        case XK_F13:          return GLFW_KEY_F13;
-        case XK_F14:          return GLFW_KEY_F14;
-        case XK_F15:          return GLFW_KEY_F15;
-        case XK_F16:          return GLFW_KEY_F16;
-        case XK_F17:          return GLFW_KEY_F17;
-        case XK_F18:          return GLFW_KEY_F18;
-        case XK_F19:          return GLFW_KEY_F19;
-        case XK_F20:          return GLFW_KEY_F20;
-        case XK_F21:          return GLFW_KEY_F21;
-        case XK_F22:          return GLFW_KEY_F22;
-        case XK_F23:          return GLFW_KEY_F23;
-        case XK_F24:          return GLFW_KEY_F24;
-        case XK_F25:          return GLFW_KEY_F25;
+        case XK_Meta_R:
+        case XK_Alt_R:          return GLFW_KEY_RIGHT_ALT;
+        case XK_Super_L:        return GLFW_KEY_LEFT_SUPER;
+        case XK_Super_R:        return GLFW_KEY_RIGHT_SUPER;
+        case XK_Menu:           return GLFW_KEY_MENU;
+        case XK_Num_Lock:       return GLFW_KEY_NUM_LOCK;
+        case XK_Caps_Lock:      return GLFW_KEY_CAPS_LOCK;
+        case XK_Scroll_Lock:    return GLFW_KEY_SCROLL_LOCK;
+        case XK_Pause:          return GLFW_KEY_PAUSE;
+        case XK_Delete:         return GLFW_KEY_DELETE;
+        case XK_BackSpace:      return GLFW_KEY_BACKSPACE;
+        case XK_Return:         return GLFW_KEY_ENTER;
+        case XK_Home:           return GLFW_KEY_HOME;
+        case XK_End:            return GLFW_KEY_END;
+        case XK_Page_Up:        return GLFW_KEY_PAGE_UP;
+        case XK_Page_Down:      return GLFW_KEY_PAGE_DOWN;
+        case XK_Insert:         return GLFW_KEY_INSERT;
+        case XK_Left:           return GLFW_KEY_LEFT;
+        case XK_Right:          return GLFW_KEY_RIGHT;
+        case XK_Down:           return GLFW_KEY_DOWN;
+        case XK_Up:             return GLFW_KEY_UP;
+        case XK_F1:             return GLFW_KEY_F1;
+        case XK_F2:             return GLFW_KEY_F2;
+        case XK_F3:             return GLFW_KEY_F3;
+        case XK_F4:             return GLFW_KEY_F4;
+        case XK_F5:             return GLFW_KEY_F5;
+        case XK_F6:             return GLFW_KEY_F6;
+        case XK_F7:             return GLFW_KEY_F7;
+        case XK_F8:             return GLFW_KEY_F8;
+        case XK_F9:             return GLFW_KEY_F9;
+        case XK_F10:            return GLFW_KEY_F10;
+        case XK_F11:            return GLFW_KEY_F11;
+        case XK_F12:            return GLFW_KEY_F12;
+        case XK_F13:            return GLFW_KEY_F13;
+        case XK_F14:            return GLFW_KEY_F14;
+        case XK_F15:            return GLFW_KEY_F15;
+        case XK_F16:            return GLFW_KEY_F16;
+        case XK_F17:            return GLFW_KEY_F17;
+        case XK_F18:            return GLFW_KEY_F18;
+        case XK_F19:            return GLFW_KEY_F19;
+        case XK_F20:            return GLFW_KEY_F20;
+        case XK_F21:            return GLFW_KEY_F21;
+        case XK_F22:            return GLFW_KEY_F22;
+        case XK_F23:            return GLFW_KEY_F23;
+        case XK_F24:            return GLFW_KEY_F24;
+        case XK_F25:            return GLFW_KEY_F25;
 
-        // Numeric keypad (should have been detected in secondary keysym!)
-        case XK_KP_Divide:    return GLFW_KEY_KP_DIVIDE;
-        case XK_KP_Multiply:  return GLFW_KEY_KP_MULTIPLY;
-        case XK_KP_Subtract:  return GLFW_KEY_KP_SUBTRACT;
-        case XK_KP_Add:       return GLFW_KEY_KP_ADD;
-        case XK_KP_Equal:     return GLFW_KEY_KP_EQUAL;
-        case XK_KP_Enter:     return GLFW_KEY_KP_ENTER;
+        // Numeric keypad
+        case XK_KP_Divide:      return GLFW_KEY_KP_DIVIDE;
+        case XK_KP_Multiply:    return GLFW_KEY_KP_MULTIPLY;
+        case XK_KP_Subtract:    return GLFW_KEY_KP_SUBTRACT;
+        case XK_KP_Add:         return GLFW_KEY_KP_ADD;
 
-        // The rest (should be printable keys)
-        default:
-            // Make uppercase
-            XConvertCase(key, &key_lc, &key_uc);
-            key = key_uc;
-
-            // Valid ISO 8859-1 character?
-            if ((key >=  32 && key <= 126) || (key >= 160 && key <= 255))
-                return (int) key;
-
-            return GLFW_KEY_UNKNOWN;
+        // These should have been detected in secondary keysym test above!
+        case XK_KP_Insert:      return GLFW_KEY_KP_0;
+        case XK_KP_End:         return GLFW_KEY_KP_1;
+        case XK_KP_Down:        return GLFW_KEY_KP_2;
+        case XK_KP_Page_Down:   return GLFW_KEY_KP_3;
+        case XK_KP_Left:        return GLFW_KEY_KP_4;
+        case XK_KP_Right:       return GLFW_KEY_KP_6;
+        case XK_KP_Home:        return GLFW_KEY_KP_7;
+        case XK_KP_Up:          return GLFW_KEY_KP_8;
+        case XK_KP_Page_Up:     return GLFW_KEY_KP_9;
+        case XK_KP_Delete:      return GLFW_KEY_KP_DECIMAL;
+        case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
+        case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
+        default:                break;
     }
+
+    // At this point we should only have printable keys left. We try the
+    // pre-filled LUT first (which is layout independent), which should give
+    // a positive result if we have the Xkb extension.
+    if ((keycode >= 0) && (keycode < 256))
+    {
+        int result = _glfwLibrary.X11.Xkb.keyCodeLUT[keycode];
+        if (result >= 0)
+        {
+            return result;
+        }
+    }
+
+    // Last resort: Check the pimary keysym for printable keys. This will
+    // give a layout dependent mapping (which is wrong, and we may miss some
+    // keys, especially on non-US keyboards), but it's better than nothing...
+    switch (key)
+    {
+        case XK_a:              return GLFW_KEY_A;
+        case XK_b:              return GLFW_KEY_B;
+        case XK_c:              return GLFW_KEY_C;
+        case XK_d:              return GLFW_KEY_D;
+        case XK_e:              return GLFW_KEY_E;
+        case XK_f:              return GLFW_KEY_F;
+        case XK_g:              return GLFW_KEY_G;
+        case XK_h:              return GLFW_KEY_H;
+        case XK_i:              return GLFW_KEY_I;
+        case XK_j:              return GLFW_KEY_J;
+        case XK_k:              return GLFW_KEY_K;
+        case XK_l:              return GLFW_KEY_L;
+        case XK_m:              return GLFW_KEY_M;
+        case XK_n:              return GLFW_KEY_N;
+        case XK_o:              return GLFW_KEY_O;
+        case XK_p:              return GLFW_KEY_P;
+        case XK_q:              return GLFW_KEY_Q;
+        case XK_r:              return GLFW_KEY_R;
+        case XK_s:              return GLFW_KEY_S;
+        case XK_t:              return GLFW_KEY_T;
+        case XK_u:              return GLFW_KEY_U;
+        case XK_v:              return GLFW_KEY_V;
+        case XK_w:              return GLFW_KEY_W;
+        case XK_x:              return GLFW_KEY_X;
+        case XK_y:              return GLFW_KEY_Y;
+        case XK_z:              return GLFW_KEY_Z;
+        case XK_1:              return GLFW_KEY_1;
+        case XK_2:              return GLFW_KEY_2;
+        case XK_3:              return GLFW_KEY_3;
+        case XK_4:              return GLFW_KEY_4;
+        case XK_5:              return GLFW_KEY_5;
+        case XK_6:              return GLFW_KEY_6;
+        case XK_7:              return GLFW_KEY_7;
+        case XK_8:              return GLFW_KEY_8;
+        case XK_9:              return GLFW_KEY_9;
+        case XK_0:              return GLFW_KEY_0;
+        case XK_space:          return GLFW_KEY_SPACE;
+        case XK_minus:          return GLFW_KEY_MINUS;
+        case XK_equal:          return GLFW_KEY_EQUAL;
+        case XK_bracketleft:    return GLFW_KEY_LEFT_SQUARE_BRACKET;
+        case XK_bracketright:   return GLFW_KEY_RIGHT_SQUARE_BRACKET;
+        case XK_backslash:      return GLFW_KEY_BACKSLASH;
+        case XK_semicolon:      return GLFW_KEY_SEMICOLON;
+        case XK_apostrophe:     return GLFW_KEY_APOSTROPHE;
+        case XK_grave:          return GLFW_KEY_GRAVE_ACCENT;
+        case XK_comma:          return GLFW_KEY_COMMA;
+        case XK_period:         return GLFW_KEY_PERIOD;
+        case XK_slash:          return GLFW_KEY_SLASH;
+        case XK_less:           return GLFW_KEY_WORLD_1; // At least in some layouts...
+        default:                break;
+    }
+
+    // No matching translation was found, so return -1
+    return -1;
 }
 
 
diff --git a/tests/events.c b/tests/events.c
index e6fda25e..2998027d 100644
--- a/tests/events.c
+++ b/tests/events.c
@@ -46,8 +46,59 @@ static const char* get_key_name(int key)
 {
     switch (key)
     {
-        case GLFW_KEY_UNKNOWN:      return "unknown";
+        // Printable keys
+        case GLFW_KEY_A:            return "a";
+        case GLFW_KEY_B:            return "b";
+        case GLFW_KEY_C:            return "c";
+        case GLFW_KEY_D:            return "d";
+        case GLFW_KEY_E:            return "e";
+        case GLFW_KEY_F:            return "f";
+        case GLFW_KEY_G:            return "g";
+        case GLFW_KEY_H:            return "h";
+        case GLFW_KEY_I:            return "i";
+        case GLFW_KEY_J:            return "j";
+        case GLFW_KEY_K:            return "k";
+        case GLFW_KEY_L:            return "l";
+        case GLFW_KEY_M:            return "m";
+        case GLFW_KEY_N:            return "n";
+        case GLFW_KEY_O:            return "o";
+        case GLFW_KEY_P:            return "p";
+        case GLFW_KEY_Q:            return "q";
+        case GLFW_KEY_R:            return "r";
+        case GLFW_KEY_S:            return "s";
+        case GLFW_KEY_T:            return "t";
+        case GLFW_KEY_U:            return "u";
+        case GLFW_KEY_V:            return "v";
+        case GLFW_KEY_W:            return "w";
+        case GLFW_KEY_X:            return "x";
+        case GLFW_KEY_Y:            return "y";
+        case GLFW_KEY_Z:            return "z";
+        case GLFW_KEY_1:            return "1";
+        case GLFW_KEY_2:            return "2";
+        case GLFW_KEY_3:            return "3";
+        case GLFW_KEY_4:            return "4";
+        case GLFW_KEY_5:            return "5";
+        case GLFW_KEY_6:            return "6";
+        case GLFW_KEY_7:            return "7";
+        case GLFW_KEY_8:            return "8";
+        case GLFW_KEY_9:            return "9";
+        case GLFW_KEY_0:            return "0";
         case GLFW_KEY_SPACE:        return "space";
+        case GLFW_KEY_MINUS:        return "-";
+        case GLFW_KEY_EQUAL:        return "=";
+        case GLFW_KEY_LEFT_SQUARE_BRACKET: return "[";
+        case GLFW_KEY_RIGHT_SQUARE_BRACKET: return "]";
+        case GLFW_KEY_BACKSLASH:    return "\\";
+        case GLFW_KEY_SEMICOLON:    return ";";
+        case GLFW_KEY_APOSTROPHE:   return "'";
+        case GLFW_KEY_GRAVE_ACCENT: return "`";
+        case GLFW_KEY_COMMA:        return ",";
+        case GLFW_KEY_PERIOD:       return ".";
+        case GLFW_KEY_SLASH:        return "/";
+        case GLFW_KEY_WORLD_1:      return "world 1";
+        case GLFW_KEY_WORLD_2:      return "world 2";
+
+        // Special keys
         case GLFW_KEY_ESC:          return "escape";
         case GLFW_KEY_F1:           return "F1";
         case GLFW_KEY_F2:           return "F2";
@@ -78,19 +129,19 @@ static const char* get_key_name(int key)
         case GLFW_KEY_DOWN:         return "down";
         case GLFW_KEY_LEFT:         return "left";
         case GLFW_KEY_RIGHT:        return "right";
-        case GLFW_KEY_LSHIFT:       return "left shift";
-        case GLFW_KEY_RSHIFT:       return "right shift";
-        case GLFW_KEY_LCTRL:        return "left control";
-        case GLFW_KEY_RCTRL:        return "right control";
-        case GLFW_KEY_LALT:         return "left alt";
-        case GLFW_KEY_RALT:         return "right alt";
+        case GLFW_KEY_LEFT_SHIFT:   return "left shift";
+        case GLFW_KEY_RIGHT_SHIFT:  return "right shift";
+        case GLFW_KEY_LEFT_CONTROL: return "left control";
+        case GLFW_KEY_RIGHT_CONTROL: return "right control";
+        case GLFW_KEY_LEFT_ALT:     return "left alt";
+        case GLFW_KEY_RIGHT_ALT:    return "right alt";
         case GLFW_KEY_TAB:          return "tab";
         case GLFW_KEY_ENTER:        return "enter";
         case GLFW_KEY_BACKSPACE:    return "backspace";
         case GLFW_KEY_INSERT:       return "insert";
-        case GLFW_KEY_DEL:          return "delete";
-        case GLFW_KEY_PAGEUP:       return "page up";
-        case GLFW_KEY_PAGEDOWN:     return "page down";
+        case GLFW_KEY_DELETE:       return "delete";
+        case GLFW_KEY_PAGE_UP:      return "page up";
+        case GLFW_KEY_PAGE_DOWN:    return "page down";
         case GLFW_KEY_HOME:         return "home";
         case GLFW_KEY_END:          return "end";
         case GLFW_KEY_KP_0:         return "keypad 0";
@@ -110,12 +161,12 @@ static const char* get_key_name(int key)
         case GLFW_KEY_KP_DECIMAL:   return "keypad decimal";
         case GLFW_KEY_KP_EQUAL:     return "keypad equal";
         case GLFW_KEY_KP_ENTER:     return "keypad enter";
-        case GLFW_KEY_KP_NUM_LOCK:  return "keypad num lock";
+        case GLFW_KEY_NUM_LOCK:     return "num lock";
         case GLFW_KEY_CAPS_LOCK:    return "caps lock";
         case GLFW_KEY_SCROLL_LOCK:  return "scroll lock";
         case GLFW_KEY_PAUSE:        return "pause";
-        case GLFW_KEY_LSUPER:       return "left super";
-        case GLFW_KEY_RSUPER:       return "right super";
+        case GLFW_KEY_LEFT_SUPER:   return "left super";
+        case GLFW_KEY_RIGHT_SUPER:  return "right super";
         case GLFW_KEY_MENU:         return "menu";
     }
 
@@ -231,8 +282,6 @@ static void key_callback(GLFWwindow window, int key, int action)
 
     if (name)
         printf(" (%s) was %s\n", name, get_action_name(action));
-    else if (isgraph(key))
-        printf(" (%c) was %s\n", key, get_action_name(action));
     else
         printf(" was %s\n", get_action_name(action));
 
@@ -241,7 +290,7 @@ static void key_callback(GLFWwindow window, int key, int action)
 
     switch (key)
     {
-        case 'R':
+        case GLFW_KEY_R:
         {
             keyrepeat = !keyrepeat;
             if (keyrepeat)
@@ -253,7 +302,7 @@ static void key_callback(GLFWwindow window, int key, int action)
             break;
         }
 
-        case 'S':
+        case GLFW_KEY_S:
         {
             systemkeys = !systemkeys;
             if (systemkeys)