Backends: GLUT: Update to use io.AddEventKey() will full key map (#2625, #4858)
diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp
index 2964d80..ba39939 100644
--- a/backends/imgui_impl_glut.cpp
+++ b/backends/imgui_impl_glut.cpp
@@ -5,19 +5,22 @@
 // !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
 // !!! Nowadays, prefer using GLFW or SDL instead!
 
+// Implemented features:
+//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 // Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing mouse cursor shape/visibility support.
 //  [ ] Platform: Missing clipboard support (not supported by Glut).
 //  [ ] Platform: Missing gamepad support.
 
-// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
 // Read online: https://github.com/ocornut/imgui/tree/master/docs
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2022-01-10: Inputs: calling new io.AddKeyEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
 //  2019-04-03: Misc: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h.
 //  2019-03-25: Misc: Made io.DeltaTime always above zero.
 //  2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
@@ -37,6 +40,120 @@
 
 static int g_Time = 0;          // Current time, in milliseconds
 
+// Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above.
+static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key)
+{
+    switch (key)
+    {
+        case '\t':                      return ImGuiKey_Tab;
+        case 256 + GLUT_KEY_LEFT:       return ImGuiKey_LeftArrow;
+        case 256 + GLUT_KEY_RIGHT:      return ImGuiKey_RightArrow;
+        case 256 + GLUT_KEY_UP:         return ImGuiKey_UpArrow;
+        case 256 + GLUT_KEY_DOWN:       return ImGuiKey_DownArrow;
+        case 256 + GLUT_KEY_PAGE_UP:    return ImGuiKey_PageUp;
+        case 256 + GLUT_KEY_PAGE_DOWN:  return ImGuiKey_PageDown;
+        case 256 + GLUT_KEY_HOME:       return ImGuiKey_Home;
+        case 256 + GLUT_KEY_END:        return ImGuiKey_End;
+        case 256 + GLUT_KEY_INSERT:     return ImGuiKey_Insert;
+        case 127:                       return ImGuiKey_Delete;
+        case 8:                         return ImGuiKey_Backspace;
+        case ' ':                       return ImGuiKey_Space;
+        case 13:                        return ImGuiKey_Enter;
+        case 27:                        return ImGuiKey_Escape;
+        case 39:                        return ImGuiKey_Apostrophe;
+        case 44:                        return ImGuiKey_Comma;
+        case 45:                        return ImGuiKey_Minus;
+        case 46:                        return ImGuiKey_Period;
+        case 47:                        return ImGuiKey_Slash;
+        case 59:                        return ImGuiKey_Semicolon;
+        case 61:                        return ImGuiKey_Equal;
+        case 91:                        return ImGuiKey_LeftBracket;
+        case 92:                        return ImGuiKey_Backslash;
+        case 93:                        return ImGuiKey_RightBracket;
+        case 96:                        return ImGuiKey_GraveAccent;
+        //case 0:                         return ImGuiKey_CapsLock;
+        //case 0:                         return ImGuiKey_ScrollLock;
+        case 256 + 0x006D:              return ImGuiKey_NumLock;
+        //case 0:                         return ImGuiKey_PrintScreen;
+        //case 0:                         return ImGuiKey_Pause;
+        //case '0':                       return ImGuiKey_Keypad0;
+        //case '1':                       return ImGuiKey_Keypad1;
+        //case '2':                       return ImGuiKey_Keypad2;
+        //case '3':                       return ImGuiKey_Keypad3;
+        //case '4':                       return ImGuiKey_Keypad4;
+        //case '5':                       return ImGuiKey_Keypad5;
+        //case '6':                       return ImGuiKey_Keypad6;
+        //case '7':                       return ImGuiKey_Keypad7;
+        //case '8':                       return ImGuiKey_Keypad8;
+        //case '9':                       return ImGuiKey_Keypad9;
+        //case 46:                        return ImGuiKey_KeypadDecimal;
+        //case 47:                        return ImGuiKey_KeypadDivide;
+        case 42:                        return ImGuiKey_KeypadMultiply;
+        //case 45:                        return ImGuiKey_KeypadSubtract;
+        case 43:                        return ImGuiKey_KeypadAdd;
+        //case 13:                        return ImGuiKey_KeypadEnter;
+        //case 0:                         return ImGuiKey_KeypadEqual;
+        case 256 + 0x0070:              return ImGuiKey_LeftShift;
+        case 256 + 0x0072:              return ImGuiKey_LeftControl;
+        case 256 + 0x0074:              return ImGuiKey_LeftAlt;
+        //case 0:                         return ImGuiKey_LeftSuper;
+        case 256 + 0x0071:              return ImGuiKey_RightShift;
+        case 256 + 0x0073:              return ImGuiKey_RightControl;
+        case 256 + 0x0075:              return ImGuiKey_RightAlt;
+        //case 0:                         return ImGuiKey_RightSuper;
+        //case 0:                         return ImGuiKey_Menu;
+        case '0':                       return ImGuiKey_0;
+        case '1':                       return ImGuiKey_1;
+        case '2':                       return ImGuiKey_2;
+        case '3':                       return ImGuiKey_3;
+        case '4':                       return ImGuiKey_4;
+        case '5':                       return ImGuiKey_5;
+        case '6':                       return ImGuiKey_6;
+        case '7':                       return ImGuiKey_7;
+        case '8':                       return ImGuiKey_8;
+        case '9':                       return ImGuiKey_9;
+        case 'A': case 'a':             return ImGuiKey_A;
+        case 'B': case 'b':             return ImGuiKey_B;
+        case 'C': case 'c':             return ImGuiKey_C;
+        case 'D': case 'd':             return ImGuiKey_D;
+        case 'E': case 'e':             return ImGuiKey_E;
+        case 'F': case 'f':             return ImGuiKey_F;
+        case 'G': case 'g':             return ImGuiKey_G;
+        case 'H': case 'h':             return ImGuiKey_H;
+        case 'I': case 'i':             return ImGuiKey_I;
+        case 'J': case 'j':             return ImGuiKey_J;
+        case 'K': case 'k':             return ImGuiKey_K;
+        case 'L': case 'l':             return ImGuiKey_L;
+        case 'M': case 'm':             return ImGuiKey_M;
+        case 'N': case 'n':             return ImGuiKey_N;
+        case 'O': case 'o':             return ImGuiKey_O;
+        case 'P': case 'p':             return ImGuiKey_P;
+        case 'Q': case 'q':             return ImGuiKey_Q;
+        case 'R': case 'r':             return ImGuiKey_R;
+        case 'S': case 's':             return ImGuiKey_S;
+        case 'T': case 't':             return ImGuiKey_T;
+        case 'U': case 'u':             return ImGuiKey_U;
+        case 'V': case 'v':             return ImGuiKey_V;
+        case 'W': case 'w':             return ImGuiKey_W;
+        case 'X': case 'x':             return ImGuiKey_X;
+        case 'Y': case 'y':             return ImGuiKey_Y;
+        case 'Z': case 'z':             return ImGuiKey_Z;
+        case 256 + GLUT_KEY_F1:         return ImGuiKey_F1;
+        case 256 + GLUT_KEY_F2:         return ImGuiKey_F2;
+        case 256 + GLUT_KEY_F3:         return ImGuiKey_F3;
+        case 256 + GLUT_KEY_F4:         return ImGuiKey_F4;
+        case 256 + GLUT_KEY_F5:         return ImGuiKey_F5;
+        case 256 + GLUT_KEY_F6:         return ImGuiKey_F6;
+        case 256 + GLUT_KEY_F7:         return ImGuiKey_F7;
+        case 256 + GLUT_KEY_F8:         return ImGuiKey_F8;
+        case 256 + GLUT_KEY_F9:         return ImGuiKey_F9;
+        case 256 + GLUT_KEY_F10:        return ImGuiKey_F10;
+        case 256 + GLUT_KEY_F11:        return ImGuiKey_F11;
+        case 256 + GLUT_KEY_F12:        return ImGuiKey_F12;
+        default:                        return ImGuiKey_None;
+    }
+}
+
 bool ImGui_ImplGLUT_Init()
 {
     ImGuiIO& io = ImGui::GetIO();
@@ -46,33 +163,8 @@
 #else
     io.BackendPlatformName = "imgui_impl_glut";
 #endif
-
     g_Time = 0;
 
-    // Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above.
-    io.KeyMap[ImGuiKey_Tab]         = '\t'; // == 9 == CTRL+I
-    io.KeyMap[ImGuiKey_LeftArrow]   = 256 + GLUT_KEY_LEFT;
-    io.KeyMap[ImGuiKey_RightArrow]  = 256 + GLUT_KEY_RIGHT;
-    io.KeyMap[ImGuiKey_UpArrow]     = 256 + GLUT_KEY_UP;
-    io.KeyMap[ImGuiKey_DownArrow]   = 256 + GLUT_KEY_DOWN;
-    io.KeyMap[ImGuiKey_PageUp]      = 256 + GLUT_KEY_PAGE_UP;
-    io.KeyMap[ImGuiKey_PageDown]    = 256 + GLUT_KEY_PAGE_DOWN;
-    io.KeyMap[ImGuiKey_Home]        = 256 + GLUT_KEY_HOME;
-    io.KeyMap[ImGuiKey_End]         = 256 + GLUT_KEY_END;
-    io.KeyMap[ImGuiKey_Insert]      = 256 + GLUT_KEY_INSERT;
-    io.KeyMap[ImGuiKey_Delete]      = 127;
-    io.KeyMap[ImGuiKey_Backspace]   = 8;  // == CTRL+H
-    io.KeyMap[ImGuiKey_Space]       = ' ';
-    io.KeyMap[ImGuiKey_Enter]       = 13; // == CTRL+M
-    io.KeyMap[ImGuiKey_Escape]      = 27;
-    io.KeyMap[ImGuiKey_KeypadEnter] = 13; // == CTRL+M
-    io.KeyMap[ImGuiKey_A]           = 'A';
-    io.KeyMap[ImGuiKey_C]           = 'C';
-    io.KeyMap[ImGuiKey_V]           = 'V';
-    io.KeyMap[ImGuiKey_X]           = 'X';
-    io.KeyMap[ImGuiKey_Y]           = 'Y';
-    io.KeyMap[ImGuiKey_Z]           = 'Z';
-
     return true;
 }
 
@@ -117,6 +209,14 @@
     io.KeyCtrl = (mods & GLUT_ACTIVE_CTRL) != 0;
     io.KeyShift = (mods & GLUT_ACTIVE_SHIFT) != 0;
     io.KeyAlt = (mods & GLUT_ACTIVE_ALT) != 0;
+    io.KeySuper = false;
+}
+
+static void ImGui_ImplGLUT_AddKeyEvent(ImGuiKey key, bool down, int native_keycode)
+{
+    ImGuiIO& io = ImGui::GetIO();
+    io.AddKeyEvent(key, down);
+    io.SetKeyEventNativeData(key, native_keycode, -1); // To support legacy indexing (<1.87 user code)
 }
 
 void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y)
@@ -127,16 +227,8 @@
     if (c >= 32)
         io.AddInputCharacter((unsigned int)c);
 
-    // Store letters in KeysDown[] array as both uppercase and lowercase + Handle GLUT translating CTRL+A..CTRL+Z as 1..26.
-    // This is a hacky mess but GLUT is unable to distinguish e.g. a TAB key from CTRL+I so this is probably the best we can do here.
-    if (c >= 1 && c <= 26)
-        io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = true;
-    else if (c >= 'a' && c <= 'z')
-        io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = true;
-    else if (c >= 'A' && c <= 'Z')
-        io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = true;
-    else
-        io.KeysDown[c] = true;
+    ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c);
+    ImGui_ImplGLUT_AddKeyEvent(key, true, c);
     ImGui_ImplGLUT_UpdateKeyboardMods();
     (void)x; (void)y; // Unused
 }
@@ -144,15 +236,8 @@
 void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
 {
     //printf("char_up_func %d '%c'\n", c, c);
-    ImGuiIO& io = ImGui::GetIO();
-    if (c >= 1 && c <= 26)
-        io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = false;
-    else if (c >= 'a' && c <= 'z')
-        io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = false;
-    else if (c >= 'A' && c <= 'Z')
-        io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = false;
-    else
-        io.KeysDown[c] = false;
+    ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c);
+    ImGui_ImplGLUT_AddKeyEvent(key, false, c);
     ImGui_ImplGLUT_UpdateKeyboardMods();
     (void)x; (void)y; // Unused
 }
@@ -160,9 +245,8 @@
 void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y)
 {
     //printf("key_down_func %d\n", key);
-    ImGuiIO& io = ImGui::GetIO();
-    if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
-        io.KeysDown[key + 256] = true;
+    ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256);
+    ImGui_ImplGLUT_AddKeyEvent(imgui_key, true, key + 256);
     ImGui_ImplGLUT_UpdateKeyboardMods();
     (void)x; (void)y; // Unused
 }
@@ -170,9 +254,8 @@
 void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y)
 {
     //printf("key_up_func %d\n", key);
-    ImGuiIO& io = ImGui::GetIO();
-    if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
-        io.KeysDown[key + 256] = false;
+    ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256);
+    ImGui_ImplGLUT_AddKeyEvent(imgui_key, false, key + 256);
     ImGui_ImplGLUT_UpdateKeyboardMods();
     (void)x; (void)y; // Unused
 }
diff --git a/backends/imgui_impl_glut.h b/backends/imgui_impl_glut.h
index 96c779f..98d4e59 100644
--- a/backends/imgui_impl_glut.h
+++ b/backends/imgui_impl_glut.h
@@ -5,13 +5,15 @@
 // !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
 // !!! Nowadays, prefer using GLFW or SDL instead!
 
+// Implemented features:
+//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 // Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing mouse cursor shape/visibility support.
 //  [ ] Platform: Missing clipboard support (not supported by Glut).
 //  [ ] Platform: Missing gamepad support.
 
-// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
 // Read online: https://github.com/ocornut/imgui/tree/master/docs