From 95516356842e2469b59ad590c7918bf9f40683bf Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Jan 2022 18:42:18 +0100 Subject: [PATCH 01/12] IO: fix SetKeyEventNativeData() not handling ImGuiKey_None the same way as AddKeyEvent(). (#4905, #4858) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index c963db4ed..3f77768e9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1266,6 +1266,8 @@ void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) // If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index) { + if (key == ImGuiKey_None) + return; IM_ASSERT(ImGui::IsNamedKey(key)); // >= 512 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey(native_legacy_index)); // >= 0 && <= 511 IM_UNUSED(native_keycode); // Yet unused From 553b04883ee3e329ab7ce81a4ebbdb2360e92f21 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Jan 2022 18:52:19 +0100 Subject: [PATCH 02/12] Backends: SDL: Fix for Emscriptem. Amend 98ce013. --- backends/imgui_impl_sdl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index f01095471..8feef9c25 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -424,7 +424,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() { int window_x, window_y, mouse_x_global, mouse_y_global; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); - SDL_GetWindowPosition(focused_window, &window_x, &window_y); + SDL_GetWindowPosition(bd->Window, &window_x, &window_y); io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); } } From 6188e941086fffd224cf49fc66ec8ed492607736 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Jan 2022 19:18:31 +0100 Subject: [PATCH 03/12] Examples: Vulkan: fill Subpass and MSAASamples to increase discoverability (#4886) + IO docs update (#4858) https://github.com/mosra/magnum-integration/pull/89 --- backends/imgui_impl_vulkan.h | 4 ++-- docs/CHANGELOG.txt | 4 +++- examples/example_glfw_vulkan/main.cpp | 4 +++- examples/example_sdl_vulkan/main.cpp | 4 +++- imgui.cpp | 1 + 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index c770d0c1e..abfecc872 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -6,7 +6,7 @@ // Missing features: // [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914 -// 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 @@ -56,7 +56,7 @@ struct ImGui_ImplVulkan_InitInfo uint32_t Subpass; uint32_t MinImageCount; // >= 2 uint32_t ImageCount; // >= MinImageCount - VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT + VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT (0 -> default to VK_SAMPLE_COUNT_1_BIT) const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); }; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 58604c9a2..832e61f68 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -48,11 +48,13 @@ Breaking Changes: - IsKeyDown(), IsKeyPressed(), IsKeyReleased(), GetKeyPressedAmount(). - All backends were updated to use io.AddKeyEvent(). - Backward compatibility: - - Old backends populating those arrays will still work! (for a while) + - Old backends populating those arrays should still work! (for a while) - Calling e.g. IsKeyPressed(MY_NATIVE_KEY_XXX) will still work! (for a while) - Those legacy arrays will only be disabled if '#define IMGUI_DISABLE_OBSOLETE_KEYIO' is set in your imconfig. In a few versions, IMGUI_DISABLE_OBSOLETE_FUNCTIONS will automatically enable IMGUI_DISABLE_OBSOLETE_KEYIO, so this will be moved into the regular obsolescence path. + - BREAKING: If your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") + this is a use case that will now assert and be breaking for your old backend. - Transition guide: - IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 615f2ee1d..2469be602 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -404,9 +404,11 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.Allocator = g_Allocator; + init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + init_info.Allocator = g_Allocator; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 2c01afef1..9a26ae4f9 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -396,9 +396,11 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.Allocator = g_Allocator; + init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + init_info.Allocator = g_Allocator; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); diff --git a/imgui.cpp b/imgui.cpp index 3f77768e9..d237d1df2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -390,6 +390,7 @@ CODE - IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() + - one case won't work with backward compatibility: if your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") because those values are now larger than the legacy KeyDown[] array. Will assert. - inputs: added io.AddKeyModsEvent() instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper. - 2022/01/05 (1.87) - inputs: renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum. - 2022/01/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. From 45c4365ec3d500bf4f373d27a4c62baef991ab36 Mon Sep 17 00:00:00 2001 From: RandomErrorMessage <35673979+RandomErrorMessage@users.noreply.github.com> Date: Fri, 14 Jan 2022 04:47:53 +0000 Subject: [PATCH 04/12] Backends: GLFW: glfwGetKeyName is not implemented in emscripten (#4907, #4858) --- backends/imgui_impl_glfw.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index de6301dca..83d4bd626 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -261,7 +261,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) { -#if GLFW_HAS_GET_KEY_NAME +#if GLFW_HAS_GET_KEY_NAME && !defined(__EMSCRIPTEN__) // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult. // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently) // See https://github.com/glfw/glfw/issues/1502 for details. @@ -278,6 +278,8 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) else if (const char* p = strchr(char_names, key_name[0])) { key = char_keys[p - char_names]; } } // if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name); +#else + IM_UNUSED(scancode); #endif return key; } From f84c93d8347617326952dfb1dbb921c53df071cc Mon Sep 17 00:00:00 2001 From: Adheesh Trivedi <84070263+AdhTri001@users.noreply.github.com> Date: Sun, 16 Jan 2022 22:46:39 +0530 Subject: [PATCH 05/12] Update BACKENDS.md (#4909) --- docs/BACKENDS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 5bd2e8364..1efe1dc72 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -9,7 +9,7 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc. - The 'Renderer' backends are in charge of: creating atlas texture, rendering imgui draw data.
- e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc. + e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc. - For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same. @@ -88,7 +88,7 @@ The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/ex ### Backends for third-party frameworks, graphics API or other languages -See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, LÖVE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others). +See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, LÖVE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others). ### Recommended Backends From eb823655afc5d8b4d081526f8e1525fdea49b782 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 11:53:03 +0100 Subject: [PATCH 06/12] Removed support for pre-C++11 compilers. We'll stop supporting VS2010. (#4537) Build all --- docs/CHANGELOG.txt | 1 + imgui.h | 17 ++--------------- imgui_demo.cpp | 1 + imgui_internal.h | 4 ---- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 832e61f68..a4e4a1392 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -37,6 +37,7 @@ HOW TO UPDATE? Breaking Changes: +- Removed support for pre-C++11 compilers. We'll stop supporting VS2010. (#4537) - Reworked IO keyboard input system. (#2625, #3724) [@thedmd, @ocornut] - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. - Added io.AddKeyModsEvent() function, obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. diff --git a/imgui.h b/imgui.h index a1cfb7694..cd076cec8 100644 --- a/imgui.h +++ b/imgui.h @@ -86,11 +86,7 @@ Index of this file: #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. -#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) #define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11 -#else -#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro. -#endif // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. #if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__) @@ -228,17 +224,8 @@ typedef signed short ImS16; // 16-bit signed integer typedef unsigned short ImU16; // 16-bit unsigned integer typedef signed int ImS32; // 32-bit signed integer == int typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors) -#if defined(_MSC_VER) && !defined(__clang__) -typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio) -typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio) -#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) -#include -typedef int64_t ImS64; // 64-bit signed integer (pre C++11) -typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11) -#else -typedef signed long long ImS64; // 64-bit signed integer (post C++11) -typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) -#endif +typedef signed long long ImS64; // 64-bit signed integer (C++11) +typedef unsigned long long ImU64; // 64-bit unsigned integer (C++11) // Character types // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7e96811e7..5c5bc3a39 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -92,6 +92,7 @@ Index of this file: // Visual Studio warnings #ifdef _MSC_VER +#pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #endif diff --git a/imgui_internal.h b/imgui_internal.h index 88e09851e..bff1a61fa 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -203,11 +203,7 @@ namespace ImStb #define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log // Static Asserts -#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") -#else -#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] -#endif // "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much. // We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code. From 075576744057573083ea2dff7d8c9b46d12a28bf Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 14:57:55 +0100 Subject: [PATCH 07/12] Backends: move io.AddKeyModsEvent() next to io.AddKeyEvent() submission, rely on mods from platform/source. (#4858) + fix #2622 again broken by 746c9f7 Amended to submit modifiers before. --- backends/imgui_impl_allegro5.cpp | 27 +++++++++++++++++---------- backends/imgui_impl_glfw.cpp | 28 +++++++++++++++------------- backends/imgui_impl_glut.cpp | 10 +++++----- backends/imgui_impl_osx.mm | 23 +++++++---------------- backends/imgui_impl_sdl.cpp | 26 +++++++++++++------------- backends/imgui_impl_win32.cpp | 20 ++++++++++---------- docs/CHANGELOG.txt | 6 +++++- 7 files changed, 72 insertions(+), 68 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index ac03b3c1e..25e2d1489 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. // 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events. @@ -440,6 +441,20 @@ void ImGui_ImplAllegro5_Shutdown() IM_DELETE(bd); } +// ev->keyboard.modifiers seems always zero so using that... +static void ImGui_ImplAllegro5_UpdateKeyModifiers() +{ + ImGuiIO& io = ImGui::GetIO(); + ALLEGRO_KEYBOARD_STATE keys; + al_get_keyboard_state(&keys); + ImGuiKeyModFlags key_mods = + ((al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL)) ? ImGuiKeyModFlags_Ctrl : 0) | + ((al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT)) ? ImGuiKeyModFlags_Shift : 0) | + ((al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR)) ? ImGuiKeyModFlags_Alt : 0) | + ((al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN)) ? ImGuiKeyModFlags_Super : 0); + io.AddKeyModsEvent(key_mods); +} + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. @@ -487,6 +502,7 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) case ALLEGRO_EVENT_KEY_UP: if (ev->keyboard.display == bd->Display) { + ImGui_ImplAllegro5_UpdateKeyModifiers(); ImGuiKey key = ImGui_ImplAllegro5_KeyCodeToImGuiKey(ev->keyboard.keycode); io.AddKeyEvent(key, (ev->type == ALLEGRO_EVENT_KEY_DOWN)); io.SetKeyEventNativeData(key, ev->keyboard.keycode, -1); // To support legacy indexing (<1.87 user code) @@ -560,15 +576,6 @@ void ImGui_ImplAllegro5_NewFrame() io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; - // Setup inputs - ALLEGRO_KEYBOARD_STATE keys; - al_get_keyboard_state(&keys); - ImGuiKeyModFlags key_mods = - ((al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL)) ? ImGuiKeyModFlags_Ctrl : 0) | - ((al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT)) ? ImGuiKeyModFlags_Shift : 0) | - ((al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR)) ? ImGuiKeyModFlags_Alt : 0) | - ((al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN)) ? ImGuiKeyModFlags_Super : 0); - io.AddKeyModsEvent(key_mods); - + // Setup mouse cursor shape ImGui_ImplAllegro5_UpdateMouseCursor(); } diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 83d4bd626..b10bab89b 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback(). // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API. @@ -238,12 +239,24 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) } } +static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiKeyModFlags key_mods = + ((mods & GLFW_MOD_CONTROL) ? ImGuiKeyModFlags_Ctrl : 0) | + ((mods & GLFW_MOD_SHIFT) ? ImGuiKeyModFlags_Shift : 0) | + ((mods & GLFW_MOD_ALT) ? ImGuiKeyModFlags_Alt : 0) | + ((mods & GLFW_MOD_SUPER) ? ImGuiKeyModFlags_Super : 0); + io.AddKeyModsEvent(key_mods); +} + void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackMousebutton != NULL && window == bd->Window) bd->PrevUserCallbackMousebutton(window, button, action, mods); + ImGui_ImplGlfw_UpdateKeyModifiers(mods); if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(bd->MouseJustPressed)) bd->MouseJustPressed[button] = true; } @@ -293,6 +306,8 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i if (action != GLFW_PRESS && action != GLFW_RELEASE) return; + ImGui_ImplGlfw_UpdateKeyModifiers(mods); + keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); ImGuiIO& io = ImGui::GetIO(); @@ -557,18 +572,6 @@ static void ImGui_ImplGlfw_UpdateGamepads() io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; } -static void ImGui_ImplGlfw_UpdateKeyModifiers() -{ - ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - ImGuiIO& io = ImGui::GetIO(); - ImGuiKeyModFlags key_mods = - (((glfwGetKey(bd->Window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)) ? ImGuiKeyModFlags_Ctrl : 0) | - (((glfwGetKey(bd->Window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS)) ? ImGuiKeyModFlags_Shift : 0) | - (((glfwGetKey(bd->Window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS)) ? ImGuiKeyModFlags_Alt : 0) | - (((glfwGetKey(bd->Window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS)) ? ImGuiKeyModFlags_Super : 0); - io.AddKeyModsEvent(key_mods); -} - void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); @@ -589,7 +592,6 @@ void ImGui_ImplGlfw_NewFrame() io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; - ImGui_ImplGlfw_UpdateKeyModifiers(); ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseCursor(); diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index 6eec280e3..91185372a 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -202,7 +202,7 @@ void ImGui_ImplGLUT_NewFrame() ImGui::NewFrame(); } -static void ImGui_ImplGLUT_UpdateKeyboardMods() +static void ImGui_ImplGLUT_UpdateKeyModifiers() { ImGuiIO& io = ImGui::GetIO(); int glut_key_mods = glutGetModifiers(); @@ -230,7 +230,7 @@ void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y) ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c); ImGui_ImplGLUT_AddKeyEvent(key, true, c); - ImGui_ImplGLUT_UpdateKeyboardMods(); + ImGui_ImplGLUT_UpdateKeyModifiers(); (void)x; (void)y; // Unused } @@ -239,7 +239,7 @@ void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y) //printf("char_up_func %d '%c'\n", c, c); ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c); ImGui_ImplGLUT_AddKeyEvent(key, false, c); - ImGui_ImplGLUT_UpdateKeyboardMods(); + ImGui_ImplGLUT_UpdateKeyModifiers(); (void)x; (void)y; // Unused } @@ -248,7 +248,7 @@ void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y) //printf("key_down_func %d\n", key); ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256); ImGui_ImplGLUT_AddKeyEvent(imgui_key, true, key + 256); - ImGui_ImplGLUT_UpdateKeyboardMods(); + ImGui_ImplGLUT_UpdateKeyModifiers(); (void)x; (void)y; // Unused } @@ -257,7 +257,7 @@ void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y) //printf("key_up_func %d\n", key); ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256); ImGui_ImplGLUT_AddKeyEvent(imgui_key, false, key + 256); - ImGui_ImplGLUT_UpdateKeyboardMods(); + ImGui_ImplGLUT_UpdateKeyModifiers(); (void)x; (void)y; // Unused } diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 55f269d18..648840dd8 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -53,7 +53,6 @@ static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static bool g_MouseCursorHidden = false; static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; static bool g_MouseDown[ImGuiMouseButton_COUNT] = {}; -static ImGuiKeyModFlags g_KeyModifiers = ImGuiKeyModFlags_None; static ImFocusObserver* g_FocusObserver = nil; static KeyEventResponder* g_KeyEventResponder = nil; static NSTextInputContext* g_InputContext = nil; @@ -535,12 +534,6 @@ static void ImGui_ImplOSX_UpdateGamepads() io.BackendFlags |= ImGuiBackendFlags_HasGamepad; } -static void ImGui_ImplOSX_UpdateKeyModifiers() -{ - ImGuiIO& io = ImGui::GetIO(); - io.AddKeyModsEvent(g_KeyModifiers); -} - static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view) { ImGuiIO& io = ImGui::GetIO(); @@ -569,7 +562,6 @@ void ImGui_ImplOSX_NewFrame(NSView* view) io.DeltaTime = (float)(current_time - g_Time); g_Time = current_time; - ImGui_ImplOSX_UpdateKeyModifiers(); ImGui_ImplOSX_UpdateMouseCursorAndButtons(); ImGui_ImplOSX_UpdateGamepads(); ImGui_ImplOSX_UpdateImePosWithView(view); @@ -666,17 +658,16 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) unsigned short key_code = [event keyCode]; unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; - ImGuiKeyModFlags imgui_flags = ImGuiKeyModFlags_None; + ImGuiKeyModFlags imgui_key_mods = ImGuiKeyModFlags_None; if (flags & NSEventModifierFlagShift) - imgui_flags |= ImGuiKeyModFlags_Shift; + imgui_key_mods |= ImGuiKeyModFlags_Shift; if (flags & NSEventModifierFlagControl) - imgui_flags |= ImGuiKeyModFlags_Ctrl; + imgui_key_mods |= ImGuiKeyModFlags_Ctrl; if (flags & NSEventModifierFlagOption) - imgui_flags |= ImGuiKeyModFlags_Alt; + imgui_key_mods |= ImGuiKeyModFlags_Alt; if (flags & NSEventModifierFlagCommand) - imgui_flags |= ImGuiKeyModFlags_Super; - - g_KeyModifiers = imgui_flags; + imgui_key_mods |= ImGuiKeyModFlags_Super; + io.AddKeyModsEvent(imgui_key_mods); ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code); if (key != ImGuiKey_None) @@ -705,7 +696,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) } else if (imgui_mask) { - io.AddKeyEvent(key, (imgui_flags & imgui_mask) != 0); + io.AddKeyEvent(key, (imgui_key_mods & imgui_mask) != 0); } io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code) } diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 8feef9c25..941acaec3 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. // 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. @@ -222,6 +223,17 @@ static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) return ImGuiKey_None; } +static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiKeyModFlags key_mods = + ((sdl_key_mods & KMOD_CTRL) ? ImGuiKeyModFlags_Ctrl : 0) | + ((sdl_key_mods & KMOD_SHIFT) ? ImGuiKeyModFlags_Shift : 0) | + ((sdl_key_mods & KMOD_ALT) ? ImGuiKeyModFlags_Alt : 0) | + ((sdl_key_mods & KMOD_GUI) ? ImGuiKeyModFlags_Super : 0); + io.AddKeyModsEvent(key_mods); +} + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. @@ -269,6 +281,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_KEYDOWN: case SDL_KEYUP: { + ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym); io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. @@ -499,18 +512,6 @@ static void ImGui_ImplSDL2_UpdateGamepads() #undef MAP_ANALOG } -static void ImGui_ImplSDL2_UpdateKeyModifiers() -{ - ImGuiIO& io = ImGui::GetIO(); - SDL_Keymod sdl_key_mods = SDL_GetModState(); - ImGuiKeyModFlags key_mods = - ((sdl_key_mods & KMOD_CTRL) ? ImGuiKeyModFlags_Ctrl : 0) | - ((sdl_key_mods & KMOD_SHIFT) ? ImGuiKeyModFlags_Shift : 0) | - ((sdl_key_mods & KMOD_ALT) ? ImGuiKeyModFlags_Alt : 0) | - ((sdl_key_mods & KMOD_GUI) ? ImGuiKeyModFlags_Super : 0); - io.AddKeyModsEvent(key_mods); -} - void ImGui_ImplSDL2_NewFrame() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); @@ -534,7 +535,6 @@ void ImGui_ImplSDL2_NewFrame() io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); bd->Time = current_time; - ImGui_ImplSDL2_UpdateKeyModifiers(); ImGui_ImplSDL2_UpdateMouseData(); ImGui_ImplSDL2_UpdateMouseCursor(); diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index bd3d54784..379434651 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -34,8 +34,9 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-12: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. -// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. +// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before a key event (not in NewFrame) to fix input queue with very low framerates. +// 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. +// 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness. // 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. @@ -235,10 +236,10 @@ static void ImGui_ImplWin32_UpdateKeyModifiers() { ImGuiIO& io = ImGui::GetIO(); ImGuiKeyModFlags key_mods = - ((IsVkDown(VK_LCONTROL) || IsVkDown(VK_RCONTROL)) ? ImGuiKeyModFlags_Ctrl : 0) | - ((IsVkDown(VK_LSHIFT) || IsVkDown(VK_RSHIFT)) ? ImGuiKeyModFlags_Shift : 0) | - ((IsVkDown(VK_LMENU) || IsVkDown(VK_RMENU)) ? ImGuiKeyModFlags_Alt : 0) | - ((IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN)) ? ImGuiKeyModFlags_Super : 0); + ((IsVkDown(VK_CONTROL)) ? ImGuiKeyModFlags_Ctrl : 0) | + ((IsVkDown(VK_SHIFT) ) ? ImGuiKeyModFlags_Shift : 0) | + ((IsVkDown(VK_MENU)) ? ImGuiKeyModFlags_Alt : 0) | + ((IsVkDown(VK_APPS)) ? ImGuiKeyModFlags_Super : 0); io.AddKeyModsEvent(key_mods); } @@ -342,9 +343,6 @@ void ImGui_ImplWin32_NewFrame() // Process workarounds for known Windows key handling issues ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); - // Update key modifiers - ImGui_ImplWin32_UpdateKeyModifiers(); - // Update OS mouse cursor with the cursor requested by imgui ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (bd->LastMouseCursor != mouse_cursor) @@ -564,9 +562,11 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA case WM_SYSKEYUP: { const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); - if (wParam < 256) { + // Submit modifiers + ImGui_ImplWin32_UpdateKeyModifiers(); + // Obtain virtual key code // (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.) int vk = (int)wParam; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a4e4a1392..d60c83651 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -103,13 +103,17 @@ Other Changes: - Backends: GLFW: Pass localized keys (matching keyboard layout). Fix e.g. CTRL+A, CTRL+Z, CTRL+Y shortcuts. We are now converting GLFW untranslated keycodes back to translated keycodes in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API. (#456, #2625) +- Backends: GLFW: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: GLFW: Update mouse position using glfwSetCursorPosCallback() + fallback when focused but not hovered/captured. +- Backends: Win32: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: Win32: Update mouse position using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback when focused but not hovered/captured. - Backends: Win32: Maintain a MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. - Backends: SDL: Pass localized keys (matching keyboard layout). Fix e.g. CTRL+A, CTRL+Z, CTRL+Y shortcuts. +- Backends: SDL: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: SDL: Update mouse position using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback when focused but not hovered/captured. - Backends: SDL: Maintain a MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. -- Backends: Allegro5, GLFW, GLUT, SDL, OSX, Win32, Android: Updated to use io.AddKeyEvent() with full key range. (#2625) [@thedmd] +- Backends: Allegro5: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) +- Backends: Android, GLUT, OSX: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: OpenGL3: Fixed a buffer overflow in imgui_impl_opengl3_loader.h init (added in 1.86). (#4468, #4830) [@dymk] It would generally not have noticeable side-effect at runtime but would be detected by runtime checkers. - Backends: Metal: Added Apple Metal C++ API support. (#4824, #4746) [@luigifcruz] From 92c4ff1c2f332f90da7bd87e5d92a25607aa0b03 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 15:41:04 +0100 Subject: [PATCH 08/12] Rename ImGuiKey_LeftControl to ImGuiKey_LeftCtrl, ImGuiKey_RightControl to ImGuiKey_RightCtrl + made key order match mods order. (#4858) --- backends/imgui_impl_allegro5.cpp | 4 ++-- backends/imgui_impl_android.cpp | 4 ++-- backends/imgui_impl_glfw.cpp | 4 ++-- backends/imgui_impl_glut.cpp | 4 ++-- backends/imgui_impl_osx.mm | 10 +++++----- backends/imgui_impl_sdl.cpp | 4 ++-- backends/imgui_impl_win32.cpp | 8 ++++---- imgui.cpp | 4 ++-- imgui.h | 6 +++--- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 25e2d1489..2a5868d83 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -329,12 +329,12 @@ static ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code) case ALLEGRO_KEY_PAD_PLUS: return ImGuiKey_KeypadAdd; case ALLEGRO_KEY_PAD_ENTER: return ImGuiKey_KeypadEnter; case ALLEGRO_KEY_PAD_EQUALS: return ImGuiKey_KeypadEqual; + case ALLEGRO_KEY_LCTRL: return ImGuiKey_LeftCtrl; case ALLEGRO_KEY_LSHIFT: return ImGuiKey_LeftShift; - case ALLEGRO_KEY_LCTRL: return ImGuiKey_LeftControl; case ALLEGRO_KEY_ALT: return ImGuiKey_LeftAlt; case ALLEGRO_KEY_LWIN: return ImGuiKey_LeftSuper; + case ALLEGRO_KEY_RCTRL: return ImGuiKey_RightCtrl; case ALLEGRO_KEY_RSHIFT: return ImGuiKey_RightShift; - case ALLEGRO_KEY_RCTRL: return ImGuiKey_RightControl; case ALLEGRO_KEY_ALTGR: return ImGuiKey_RightAlt; case ALLEGRO_KEY_RWIN: return ImGuiKey_RightSuper; case ALLEGRO_KEY_MENU: return ImGuiKey_Menu; diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp index fdf482fc9..380e4f9de 100644 --- a/backends/imgui_impl_android.cpp +++ b/backends/imgui_impl_android.cpp @@ -101,12 +101,12 @@ static ImGuiKey ImGui_ImplAndroid_KeyCodeToImGuiKey(int32_t key_code) case AKEYCODE_NUMPAD_ADD: return ImGuiKey_KeypadAdd; case AKEYCODE_NUMPAD_ENTER: return ImGuiKey_KeypadEnter; case AKEYCODE_NUMPAD_EQUALS: return ImGuiKey_KeypadEqual; + case AKEYCODE_CTRL_LEFT: return ImGuiKey_LeftCtrl; case AKEYCODE_SHIFT_LEFT: return ImGuiKey_LeftShift; - case AKEYCODE_CTRL_LEFT: return ImGuiKey_LeftControl; case AKEYCODE_ALT_LEFT: return ImGuiKey_LeftAlt; case AKEYCODE_META_LEFT: return ImGuiKey_LeftSuper; + case AKEYCODE_CTRL_RIGHT: return ImGuiKey_RightCtrl; case AKEYCODE_SHIFT_RIGHT: return ImGuiKey_RightShift; - case AKEYCODE_CTRL_RIGHT: return ImGuiKey_RightControl; case AKEYCODE_ALT_RIGHT: return ImGuiKey_RightAlt; case AKEYCODE_META_RIGHT: return ImGuiKey_RightSuper; case AKEYCODE_MENU: return ImGuiKey_Menu; diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index b10bab89b..ae98581f1 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -179,11 +179,11 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) case GLFW_KEY_KP_ENTER: return ImGuiKey_KeypadEnter; case GLFW_KEY_KP_EQUAL: return ImGuiKey_KeypadEqual; case GLFW_KEY_LEFT_SHIFT: return ImGuiKey_LeftShift; - case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftControl; + case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftCtrl; case GLFW_KEY_LEFT_ALT: return ImGuiKey_LeftAlt; case GLFW_KEY_LEFT_SUPER: return ImGuiKey_LeftSuper; case GLFW_KEY_RIGHT_SHIFT: return ImGuiKey_RightShift; - case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightControl; + case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightCtrl; case GLFW_KEY_RIGHT_ALT: return ImGuiKey_RightAlt; case GLFW_KEY_RIGHT_SUPER: return ImGuiKey_RightSuper; case GLFW_KEY_MENU: return ImGuiKey_Menu; diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index 91185372a..a316c895c 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -93,12 +93,12 @@ static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key) case 43: return ImGuiKey_KeypadAdd; //case 13: return ImGuiKey_KeypadEnter; //case 0: return ImGuiKey_KeypadEqual; + case 256 + 0x0072: return ImGuiKey_LeftCtrl; 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 + 0x0073: return ImGuiKey_RightCtrl; 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; diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 648840dd8..48a50f1b2 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -301,15 +301,15 @@ static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code) case kVK_Space: return ImGuiKey_Space; case kVK_Delete: return ImGuiKey_Backspace; case kVK_Escape: return ImGuiKey_Escape; - case kVK_Command: return ImGuiKey_LeftSuper; - case kVK_Shift: return ImGuiKey_LeftShift; case kVK_CapsLock: return ImGuiKey_CapsLock; + case kVK_Control: return ImGuiKey_LeftCtrl; + case kVK_Shift: return ImGuiKey_LeftShift; case kVK_Option: return ImGuiKey_LeftAlt; - case kVK_Control: return ImGuiKey_LeftControl; - case kVK_RightCommand: return ImGuiKey_RightSuper; + case kVK_Command: return ImGuiKey_LeftSuper; + case kVK_RightControl: return ImGuiKey_RightCtrl; case kVK_RightShift: return ImGuiKey_RightShift; case kVK_RightOption: return ImGuiKey_RightAlt; - case kVK_RightControl: return ImGuiKey_RightControl; + case kVK_RightCommand: return ImGuiKey_RightSuper; // case kVK_Function: return ImGuiKey_; // case kVK_F17: return ImGuiKey_; // case kVK_VolumeUp: return ImGuiKey_; diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 941acaec3..480846b98 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -162,12 +162,12 @@ static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd; case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter; case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual; + case SDLK_LCTRL: return ImGuiKey_LeftCtrl; case SDLK_LSHIFT: return ImGuiKey_LeftShift; - case SDLK_LCTRL: return ImGuiKey_LeftControl; case SDLK_LALT: return ImGuiKey_LeftAlt; case SDLK_LGUI: return ImGuiKey_LeftSuper; + case SDLK_RCTRL: return ImGuiKey_RightCtrl; case SDLK_RSHIFT: return ImGuiKey_RightShift; - case SDLK_RCTRL: return ImGuiKey_RightControl; case SDLK_RALT: return ImGuiKey_RightAlt; case SDLK_RGUI: return ImGuiKey_RightSuper; case SDLK_MENU: return ImGuiKey_Menu; diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 379434651..2b140b54e 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -411,11 +411,11 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) case VK_ADD: return ImGuiKey_KeypadAdd; case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter; case VK_LSHIFT: return ImGuiKey_LeftShift; - case VK_LCONTROL: return ImGuiKey_LeftControl; + case VK_LCONTROL: return ImGuiKey_LeftCtrl; case VK_LMENU: return ImGuiKey_LeftAlt; case VK_LWIN: return ImGuiKey_LeftSuper; case VK_RSHIFT: return ImGuiKey_RightShift; - case VK_RCONTROL: return ImGuiKey_RightControl; + case VK_RCONTROL: return ImGuiKey_RightCtrl; case VK_RMENU: return ImGuiKey_RightAlt; case VK_RWIN: return ImGuiKey_RightSuper; case VK_APPS: return ImGuiKey_Menu; @@ -588,8 +588,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA } else if (vk == VK_CONTROL) { - if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftControl, is_key_down, VK_LCONTROL, scancode); } - if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightControl, is_key_down, VK_RCONTROL, scancode); } + if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } + if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } } else if (vk == VK_MENU) { diff --git a/imgui.cpp b/imgui.cpp index d237d1df2..b84b2b0f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7414,8 +7414,8 @@ static const char* const GKeyNames[] = "Backslash", "RightBracket", "GraveAccent", "CapsLock", "ScrollLock", "NumLock", "PrintScreen", "Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply", - "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", "LeftShift", "LeftControl", - "LeftAlt", "LeftSuper", "RightShift", "RightControl", "RightAlt", "RightSuper", "Menu", + "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", "LeftCtrl", "LeftShift", + "LeftAlt", "LeftSuper", "RightCtrl", "RightShift", "RightAlt", "RightSuper", "Menu", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" diff --git a/imgui.h b/imgui.h index cd076cec8..1f5df0cc0 100644 --- a/imgui.h +++ b/imgui.h @@ -65,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.87 WIP" -#define IMGUI_VERSION_NUM 18605 +#define IMGUI_VERSION_NUM 18606 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -1391,12 +1391,12 @@ enum ImGuiKey_ ImGuiKey_KeypadAdd, ImGuiKey_KeypadEnter, ImGuiKey_KeypadEqual, + ImGuiKey_LeftCtrl, ImGuiKey_LeftShift, - ImGuiKey_LeftControl, ImGuiKey_LeftAlt, ImGuiKey_LeftSuper, + ImGuiKey_RightCtrl, ImGuiKey_RightShift, - ImGuiKey_RightControl, ImGuiKey_RightAlt, ImGuiKey_RightSuper, ImGuiKey_Menu, From b6582a471ae7c13eeecb8e39c72c87a99a59657e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 16:22:32 +0100 Subject: [PATCH 09/12] Backends: OSX: Fix Game Controller nav mapping to use shoulder for both focusing and tweak speed. (#4759) --- backends/imgui_impl_osx.mm | 4 ++-- docs/CHANGELOG.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 48a50f1b2..146fff1e3 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -522,8 +522,8 @@ static void ImGui_ImplOSX_UpdateGamepads() MAP_BUTTON(ImGuiNavInput_DpadDown, dpad.down); MAP_BUTTON(ImGuiNavInput_FocusPrev, leftShoulder); MAP_BUTTON(ImGuiNavInput_FocusNext, rightShoulder); - MAP_BUTTON(ImGuiNavInput_TweakSlow, leftTrigger); - MAP_BUTTON(ImGuiNavInput_TweakFast, rightTrigger); + MAP_BUTTON(ImGuiNavInput_TweakSlow, leftShoulder); + MAP_BUTTON(ImGuiNavInput_TweakFast, rightShoulder); #undef MAP_BUTTON io.NavInputs[ImGuiNavInput_LStickLeft] = gp.leftThumbstick.left.value; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d60c83651..69f7b4fdc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -121,6 +121,7 @@ Other Changes: - Backends: Metal: Ignore ImDrawCmd where ElemCount == 0, which are normally not emitted by the library but can theorically be created by user code manipulating a ImDrawList. (#4857) - Backends: OSX: Added basic Platform IME support. (#3108, #2598) [@liuliu] +- Backends: OSX: Fix Game Controller nav mapping to use shoulder for both focusing and tweak speed. (#4759) - Backends: WebGPU: Fixed incorrect size parameters in wgpuRenderPassEncoderSetIndexBuffer() and wgpuRenderPassEncoderSetVertexBuffer() calls. (#4891) [@FeepsDev] From b8e56dce83985a49e2e236900d80980510b173f3 Mon Sep 17 00:00:00 2001 From: thedmd Date: Mon, 17 Jan 2022 17:22:37 +0100 Subject: [PATCH 10/12] IO: Added AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() api + updated all Backends. (#4858) (input queue code will be next commit) Details: note that SDL, OSX and GLFW backends removed recording of MouseJustPressed[] which will be unnecessary with input queue (which is the NEXT commit). (#2787, #1992, #3383, #2525, #1320) --- backends/imgui_impl_allegro5.cpp | 16 ++++++++-------- backends/imgui_impl_android.cpp | 16 ++++++++-------- backends/imgui_impl_glfw.cpp | 24 +++++++++--------------- backends/imgui_impl_glut.cpp | 19 ++++++++----------- backends/imgui_impl_osx.mm | 31 ++++++++++--------------------- backends/imgui_impl_sdl.cpp | 25 ++++++++----------------- backends/imgui_impl_win32.cpp | 15 ++++++++------- docs/CHANGELOG.txt | 15 ++++++++++++--- imgui.cpp | 28 +++++++++++++++++++++++++++- imgui.h | 6 +++++- 10 files changed, 103 insertions(+), 92 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 2a5868d83..cef70e636 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. @@ -469,29 +470,28 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) case ALLEGRO_EVENT_MOUSE_AXES: if (ev->mouse.display == bd->Display) { - io.MouseWheel += ev->mouse.dz; - io.MouseWheelH -= ev->mouse.dw; - io.MousePos = ImVec2(ev->mouse.x, ev->mouse.y); + io.AddMousePosEvent(ev->mouse.x, ev->mouse.y); + io.AddMouseWheelEvent(-ev->mouse.dw, ev->mouse.dz); } return true; case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: case ALLEGRO_EVENT_MOUSE_BUTTON_UP: - if (ev->mouse.display == bd->Display && ev->mouse.button <= 5) - io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN); + if (ev->mouse.display == bd->Display && ev->mouse.button > 0 && ev->mouse.button <= 5) + io.AddMouseButtonEvent(ev->mouse.button - 1, ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN); return true; case ALLEGRO_EVENT_TOUCH_MOVE: if (ev->touch.display == bd->Display) - io.MousePos = ImVec2(ev->touch.x, ev->touch.y); + io.AddMousePosEvent(ev->touch.x, ev->touch.y); return true; case ALLEGRO_EVENT_TOUCH_BEGIN: case ALLEGRO_EVENT_TOUCH_END: case ALLEGRO_EVENT_TOUCH_CANCEL: if (ev->touch.display == bd->Display && ev->touch.primary) - io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN); + io.AddMouseButtonEvent(0, ev->type == ALLEGRO_EVENT_TOUCH_BEGIN); return true; case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY: if (ev->mouse.display == bd->Display) - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); return true; case ALLEGRO_EVENT_KEY_CHAR: if (ev->keyboard.display == bd->Display) diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp index 380e4f9de..82f388a5f 100644 --- a/backends/imgui_impl_android.cpp +++ b/backends/imgui_impl_android.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-03-04: Initial version. @@ -227,26 +228,25 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event) if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER) || (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) { - io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN); - io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); + io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); + io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN); } break; case AMOTION_EVENT_ACTION_BUTTON_PRESS: case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { int32_t button_state = AMotionEvent_getButtonState(input_event); - io.MouseDown[0] = ((button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0); - io.MouseDown[1] = ((button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0); - io.MouseDown[2] = ((button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0); + io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0); + io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0); + io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0); } break; case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse) case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN - io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); + io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); break; case AMOTION_EVENT_ACTION_SCROLL: - io.MouseWheel = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index); - io.MouseWheelH = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index); + io.AddMouseWheelEvent(AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index), AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index)); break; default: break; diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index ae98581f1..4dea6238b 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback(). // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. @@ -86,7 +87,6 @@ struct ImGui_ImplGlfw_Data GlfwClientApi ClientApi; double Time; GLFWwindow* MouseWindow; - bool MouseJustPressed[ImGuiMouseButton_COUNT]; GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT]; bool InstalledCallbacks; @@ -257,8 +257,10 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti bd->PrevUserCallbackMousebutton(window, button, action, mods); ImGui_ImplGlfw_UpdateKeyModifiers(mods); - if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(bd->MouseJustPressed)) - bd->MouseJustPressed[button] = true; + + ImGuiIO& io = ImGui::GetIO(); + if (button >= 0 && button < ImGuiMouseButton_COUNT) + io.AddMouseButtonEvent(button, action == GLFW_PRESS); } void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) @@ -268,8 +270,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo bd->PrevUserCallbackScroll(window, xoffset, yoffset); ImGuiIO& io = ImGui::GetIO(); - io.MouseWheelH += (float)xoffset; - io.MouseWheel += (float)yoffset; + io.AddMouseWheelEvent((float)xoffset, (float)yoffset); } static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) @@ -333,7 +334,7 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) bd->PrevUserCallbackCursorPos(window, x, y); ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)x, (float)y); + io.AddMousePosEvent((float)x, (float)y); } void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) @@ -348,7 +349,7 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) if (!entered && bd->MouseWindow == window) { bd->MouseWindow = NULL; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } } @@ -501,16 +502,9 @@ static void ImGui_ImplGlfw_UpdateMouseData() { double mouse_x, mouse_y; glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); + io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } } - - // Update buttons - for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) - { - io.MouseDown[i] = bd->MouseJustPressed[i] || glfwGetMouseButton(bd->Window, i) != 0; - bd->MouseJustPressed[i] = false; - } } static void ImGui_ImplGlfw_UpdateMouseCursor() diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index a316c895c..85ee838d9 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + 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. @@ -264,26 +265,22 @@ void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y) void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y) { ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)x, (float)y); + io.AddMousePosEvent((float)x, (float)y); int button = -1; if (glut_button == GLUT_LEFT_BUTTON) button = 0; if (glut_button == GLUT_RIGHT_BUTTON) button = 1; if (glut_button == GLUT_MIDDLE_BUTTON) button = 2; - if (button != -1 && state == GLUT_DOWN) - io.MouseDown[button] = true; - if (button != -1 && state == GLUT_UP) - io.MouseDown[button] = false; + if (button != -1 && state == GLUT_DOWN || state == GLUT_UP) + io.AddMouseButtonEvent(button, state == GLUT_DOWN); } #ifdef __FREEGLUT_EXT_H__ void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y) { ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)x, (float)y); - if (dir > 0) - io.MouseWheel += 1.0; - else if (dir < 0) - io.MouseWheel -= 1.0; + io.AddMousePosEvent((float)x, (float)y); + if (dir != 0) + io.AddMouseWheelEvent(0.0f, dir > 0 ? 1.0f : -1.0f); (void)button; // Unused } #endif @@ -297,5 +294,5 @@ void ImGui_ImplGLUT_ReshapeFunc(int w, int h) void ImGui_ImplGLUT_MotionFunc(int x, int y) { ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2((float)x, (float)y); + io.AddMousePosEvent((float)x, (float)y); } diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 146fff1e3..58e5a09f6 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-12: Inputs: Added basic Platform IME support, hooking the io.SetPlatformImeDataFn() function. // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys. @@ -51,8 +52,6 @@ static double g_HostClockPeriod = 0.0; static double g_Time = 0.0; static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static bool g_MouseCursorHidden = false; -static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; -static bool g_MouseDown[ImGuiMouseButton_COUNT] = {}; static ImFocusObserver* g_FocusObserver = nil; static KeyEventResponder* g_KeyEventResponder = nil; static NSTextInputContext* g_InputContext = nil; @@ -450,17 +449,9 @@ void ImGui_ImplOSX_Shutdown() g_FocusObserver = NULL; } -static void ImGui_ImplOSX_UpdateMouseCursorAndButtons() +static void ImGui_ImplOSX_UpdateMouseCursor() { - // Update buttons ImGuiIO& io = ImGui::GetIO(); - for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) - { - // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - io.MouseDown[i] = g_MouseJustPressed[i] || g_MouseDown[i]; - g_MouseJustPressed[i] = false; - } - if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return; @@ -562,7 +553,7 @@ void ImGui_ImplOSX_NewFrame(NSView* view) io.DeltaTime = (float)(current_time - g_Time); g_Time = current_time; - ImGui_ImplOSX_UpdateMouseCursorAndButtons(); + ImGui_ImplOSX_UpdateMouseCursor(); ImGui_ImplOSX_UpdateGamepads(); ImGui_ImplOSX_UpdateImePosWithView(view); } @@ -574,16 +565,16 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown) { int button = (int)[event buttonNumber]; - if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown)) - g_MouseDown[button] = g_MouseJustPressed[button] = true; + if (button >= 0 && button < ImGuiMouseButton_COUNT) + io.AddMouseButtonEvent(button, true); return io.WantCaptureMouse; } if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMouseUp || event.type == NSEventTypeOtherMouseUp) { int button = (int)[event buttonNumber]; - if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown)) - g_MouseDown[button] = false; + if (button >= 0 && button < ImGuiMouseButton_COUNT) + io.AddMouseButtonEvent(button, false); return io.WantCaptureMouse; } @@ -592,7 +583,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) NSPoint mousePoint = event.locationInWindow; mousePoint = [view convertPoint:mousePoint fromView:nil]; mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y); - io.MousePos = ImVec2((float)mousePoint.x, (float)mousePoint.y); + io.AddMousePosEvent((float)mousePoint.x, (float)mousePoint.y); } if (event.type == NSEventTypeScrollWheel) @@ -632,11 +623,9 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) wheel_dx = [event deltaX]; wheel_dy = [event deltaY]; } + if (wheel_dx != 0.0 || wheel_dx != 0.0) + io.AddMouseWheelEvent((float)wheel_dx * 0.1f, (float)wheel_dy * 0.1f); - if (fabs(wheel_dx) > 0.0) - io.MouseWheelH += (float)wheel_dx * 0.1f; - if (fabs(wheel_dy) > 0.0) - io.MouseWheel += (float)wheel_dy * 0.1f; return io.WantCaptureMouse; } diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 480846b98..a04233c71 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. // 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. @@ -78,7 +79,6 @@ struct ImGui_ImplSDL2_Data SDL_Window* Window; Uint64 Time; int MouseButtonsDown; - bool MousePressed[3]; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; char* ClipboardTextData; bool MouseCanUseGlobalState; @@ -248,15 +248,14 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { case SDL_MOUSEMOTION: { - io.MousePos = ImVec2((float)event->motion.x, (float)event->motion.y); + io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y); return true; } case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) io.MouseWheelH += 1; - if (event->wheel.x < 0) io.MouseWheelH -= 1; - if (event->wheel.y > 0) io.MouseWheel += 1; - if (event->wheel.y < 0) io.MouseWheel -= 1; + float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f; + float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f; + io.AddMouseWheelEvent(wheel_x, wheel_y); return true; } case SDL_MOUSEBUTTONDOWN: @@ -268,8 +267,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; } if (mouse_button == -1) break; - if (event->type == SDL_MOUSEBUTTONDOWN) - bd->MousePressed[mouse_button] = true; + io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); return true; } @@ -290,7 +288,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_WINDOWEVENT: { if (event->window.event == SDL_WINDOWEVENT_LEAVE) - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) @@ -438,16 +436,9 @@ static void ImGui_ImplSDL2_UpdateMouseData() int window_x, window_y, mouse_x_global, mouse_y_global; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetWindowPosition(bd->Window, &window_x, &window_y); - io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); + io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); } } - - // Update buttons - Uint32 mouse_buttons = SDL_GetMouseState(NULL, NULL); - io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; - io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; - bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false; } static void ImGui_ImplSDL2_UpdateMouseCursor() diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 2b140b54e..db3462fa1 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -34,6 +34,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before a key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. // 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. @@ -265,7 +266,7 @@ static void ImGui_ImplWin32_UpdateMouseData() { POINT pos; if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) - io.MousePos = ImVec2((float)pos.x, (float)pos.y); + io.AddMousePosEvent((float)pos.x, (float)pos.y); } } } @@ -510,13 +511,13 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA ::TrackMouseEvent(&tme); bd->MouseTracked = true; } - io.MousePos = ImVec2((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam)); + io.AddMousePosEvent((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam)); break; case WM_MOUSELEAVE: if (bd->MouseHwnd == hwnd) bd->MouseHwnd = NULL; bd->MouseTracked = false; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: @@ -531,7 +532,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA if (bd->MouseButtonsDown == 0 && ::GetCapture() == NULL) ::SetCapture(hwnd); bd->MouseButtonsDown |= 1 << button; - io.MouseDown[button] = true; + io.AddMouseButtonEvent(button, true); return 0; } case WM_LBUTTONUP: @@ -547,14 +548,14 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA bd->MouseButtonsDown &= ~(1 << button); if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) ::ReleaseCapture(); - io.MouseDown[button] = false; + io.AddMouseButtonEvent(button, false); return 0; } case WM_MOUSEWHEEL: - io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); return 0; case WM_MOUSEHWHEEL: - io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + io.AddMouseWheelEvent((float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f); return 0; case WM_KEYDOWN: case WM_KEYUP: diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 69f7b4fdc..3104582cf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -38,7 +38,10 @@ HOW TO UPDATE? Breaking Changes: - Removed support for pre-C++11 compilers. We'll stop supporting VS2010. (#4537) -- Reworked IO keyboard input system. (#2625, #3724) [@thedmd, @ocornut] +- Reworked IO mouse input API: (#4858) [@thedmd, @ocornut] + - Added io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions, + obsoleting writing directly to io.MousePos, io.MouseDown[], io.MouseWheel, etc. +- Reworked IO keyboard input API: (#2625, #3724) [@thedmd, @ocornut] - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. - Added io.AddKeyModsEvent() function, obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. - Added io.SetKeyEventNativeData() function (optional) to pass native and old legacy indices. @@ -47,9 +50,10 @@ Breaking Changes: - Obsoleted GetKeyIndex(): it is now unnecessary and will now return the same value. - All keyboard related functions taking 'int user_key_index' now take 'ImGuiKey key': - IsKeyDown(), IsKeyPressed(), IsKeyReleased(), GetKeyPressedAmount(). - - All backends were updated to use io.AddKeyEvent(). + - Added io.ConfigInputEventQueue (defaulting to true) to disable input queue trickling. - Backward compatibility: - - Old backends populating those arrays should still work! (for a while) + - All backends updated to use new functions. + - Old backends populating those arrays should still work! - Calling e.g. IsKeyPressed(MY_NATIVE_KEY_XXX) will still work! (for a while) - Those legacy arrays will only be disabled if '#define IMGUI_DISABLE_OBSOLETE_KEYIO' is set in your imconfig. In a few versions, IMGUI_DISABLE_OBSOLETE_FUNCTIONS will automatically enable IMGUI_DISABLE_OBSOLETE_KEYIO, @@ -104,16 +108,21 @@ Other Changes: We are now converting GLFW untranslated keycodes back to translated keycodes in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API. (#456, #2625) - Backends: GLFW: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) +- Backends: GLFW: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4858) - Backends: GLFW: Update mouse position using glfwSetCursorPosCallback() + fallback when focused but not hovered/captured. - Backends: Win32: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: Win32: Update mouse position using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback when focused but not hovered/captured. +- Backends: Win32: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4858) - Backends: Win32: Maintain a MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. - Backends: SDL: Pass localized keys (matching keyboard layout). Fix e.g. CTRL+A, CTRL+Z, CTRL+Y shortcuts. - Backends: SDL: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) - Backends: SDL: Update mouse position using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback when focused but not hovered/captured. +- Backends: SDL: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4858) - Backends: SDL: Maintain a MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. - Backends: Allegro5: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) +- Backends: Allegro5: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4858) - Backends: Android, GLUT, OSX: Submit keys using io.AddKeyEvent(). Submit keymods using io.AddKeyModsEvent() at the same time. (#2625) +- Backends: Android, GLUT, OSX: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4858) - Backends: OpenGL3: Fixed a buffer overflow in imgui_impl_opengl3_loader.h init (added in 1.86). (#4468, #4830) [@dymk] It would generally not have noticeable side-effect at runtime but would be detected by runtime checkers. - Backends: Metal: Added Apple Metal C++ API support. (#4824, #4746) [@luigifcruz] diff --git a/imgui.cpp b/imgui.cpp index b84b2b0f8..c4a3f902b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1262,7 +1262,7 @@ void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) KeysData[keydata_index].Down = down; } -// [Optional] Call add AddKeyEvent(). +// [Optional] Call after AddKeyEvent(). // Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices. // If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index) @@ -1294,6 +1294,32 @@ void ImGuiIO::AddKeyModsEvent(ImGuiKeyModFlags modifiers) KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0; } +// Queue a mouse move event +void ImGuiIO::AddMousePosEvent(float x, float y) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + g.IO.MousePos = ImVec2(x, y); +} + +void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + if (wheel_x == 0.0f && wheel_y == 0.0f) + return; + g.IO.MouseWheelH += wheel_x; + g.IO.MouseWheel += wheel_y; +} + +void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT); + g.IO.MouseDown[mouse_button] = down; +} + void ImGuiIO::AddFocusEvent(bool focused) { // We intentionally overwrite this and process in NewFrame(), in order to give a chance diff --git a/imgui.h b/imgui.h index 1f5df0cc0..e7b9091ad 100644 --- a/imgui.h +++ b/imgui.h @@ -65,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.87 WIP" -#define IMGUI_VERSION_NUM 18606 +#define IMGUI_VERSION_NUM 18607 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -1994,10 +1994,14 @@ struct ImGuiIO // Input Functions IMGUI_API void AddKeyEvent(ImGuiKey key, bool down); // Queue a new key down/up event. Key should be "translated" (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character) IMGUI_API void AddKeyModsEvent(ImGuiKeyModFlags modifiers);// Queue a change of Ctrl/Shift/Alt/Super modifiers + IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered) + IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change + IMGUI_API void AddMouseWheelEvent(float wh_x, float wh_y); // Queue a mouse wheel update IMGUI_API void AddFocusEvent(bool focused); // Queue an hosting application/platform windows gain or loss of focus IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string + IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually IMGUI_API void ClearInputKeys(); // [Internal] Release all keys IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode. From 7374b96f5cdf9adb1a1da033623ce2a4fd7f4934 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 17:32:25 +0100 Subject: [PATCH 11/12] IO: Added input queue. (#4858, #2787, #1992, #3383, #2525, #1320) --- docs/CHANGELOG.txt | 4 + imgui.cpp | 219 ++++++++++++++++++++++++++++++++++++++------- imgui.h | 3 +- imgui_demo.cpp | 4 +- imgui_internal.h | 46 ++++++++++ 5 files changed, 244 insertions(+), 32 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3104582cf..e0b345ac1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,7 @@ Breaking Changes: - Reworked IO mouse input API: (#4858) [@thedmd, @ocornut] - Added io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions, obsoleting writing directly to io.MousePos, io.MouseDown[], io.MouseWheel, etc. + - This enable input queue trickling to support low framerates. (#2787, #1992, #3383, #2525, #1320) - Reworked IO keyboard input API: (#2625, #3724) [@thedmd, @ocornut] - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. - Added io.AddKeyModsEvent() function, obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. @@ -94,6 +95,9 @@ Breaking Changes: Other Changes: +- IO: Added event based input queue API, which now trickles events to support low framerates. [@thedmd, @ocornut] + Previously the most common issue case (button presses in low framerates) was handled by backend. This is now + handled by core automatically for all kind of inputs. (#4858, #2787, #1992, #3383, #2525, #1320) - Fixed a situation where CTRL+Tab or Modal can occasionally lead to the creation of ImDrawCmd with zero triangles, which would makes the draw operation of some backends assert (e.g. Metal with debugging). (#4857) - Tables, ImDrawListSplitter: Fixed erroneously stripping trailing ImDrawList::AddCallback() when submitted in diff --git a/imgui.cpp b/imgui.cpp index c4a3f902b..40d014bd0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1136,6 +1136,7 @@ ImGuiIO::ImGuiIO() #else ConfigMacOSXBehaviors = false; #endif + ConfigInputEventQueue = true; ConfigInputTextCursorBlink = true; ConfigWindowsResizeFromEdges = true; ConfigWindowsMoveFromTitleBarOnly = false; @@ -1162,10 +1163,19 @@ ImGuiIO::ImGuiIO() // Pass in translated ASCII characters for text input. // - with glfw you can get those from the callback set in glfwSetCharCallback() // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message +// FIXME: Should in theory be called "AddCharacterEvent()" to be consistent with new API void ImGuiIO::AddInputCharacter(unsigned int c) { - if (c != 0) - InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + if (c == 0) + return; + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_Char; + e.Source = ImGuiInputSource_Keyboard; + e.Text.Char = c; + g.InputEventsQueue.push_back(e); } // UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so @@ -1178,7 +1188,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) if ((c & 0xFC00) == 0xD800) // High surrogate, must save { if (InputQueueSurrogate != 0) - InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); + AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); InputQueueSurrogate = c; return; } @@ -1188,7 +1198,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) { if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate { - InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); + AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); } else { @@ -1201,7 +1211,7 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) InputQueueSurrogate = 0; } - InputQueueCharacters.push_back(cp); + AddInputCharacter((unsigned)cp); } void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) @@ -1211,7 +1221,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) unsigned int c = 0; utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); if (c != 0) - InputQueueCharacters.push_back((ImWchar)c); + AddInputCharacter(c); } } @@ -1240,12 +1250,13 @@ void ImGuiIO::ClearInputKeys() // Queue a new key down/up event. // - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character) // - bool down: Is the key down? use false to signify a key release. -// FIXME: In the current version this is setting key data immediately. This will evolve into a trickling queue. void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) { //if (e->Down) { IMGUI_DEBUG_LOG("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); } if (key == ImGuiKey_None) return; + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); IM_ASSERT(ImGui::IsNamedKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API. // Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data. @@ -1254,12 +1265,15 @@ void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) if (BackendUsingLegacyKeyArrays == -1) for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!"); -#endif BackendUsingLegacyKeyArrays = 0; +#endif - // Write key - const int keydata_index = (key - ImGuiKey_KeysData_OFFSET); - KeysData[keydata_index].Down = down; + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_Key; + e.Source = ImGuiInputSource_Keyboard; + e.Key.Key = key; + e.Key.Down = down; + g.InputEventsQueue.push_back(e); } // [Optional] Call after AddKeyEvent(). @@ -1287,11 +1301,14 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native void ImGuiIO::AddKeyModsEvent(ImGuiKeyModFlags modifiers) { - KeyMods = modifiers; - KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0; - KeyShift = (modifiers & ImGuiKeyModFlags_Shift) != 0; - KeyAlt = (modifiers & ImGuiKeyModFlags_Alt) != 0; - KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0; + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_KeyMods; + e.Source = ImGuiInputSource_Keyboard; + e.KeyMods.Mods = modifiers; + g.InputEventsQueue.push_back(e); } // Queue a mouse move event @@ -1299,7 +1316,13 @@ void ImGuiIO::AddMousePosEvent(float x, float y) { ImGuiContext& g = *GImGui; IM_ASSERT(&g.IO == this && "Can only add events to current context."); - g.IO.MousePos = ImVec2(x, y); + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_MousePos; + e.Source = ImGuiInputSource_Mouse; + e.MousePos.PosX = x; + e.MousePos.PosY = y; + g.InputEventsQueue.push_back(e); } void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) @@ -1308,8 +1331,13 @@ void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) IM_ASSERT(&g.IO == this && "Can only add events to current context."); if (wheel_x == 0.0f && wheel_y == 0.0f) return; - g.IO.MouseWheelH += wheel_x; - g.IO.MouseWheel += wheel_y; + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_MouseWheel; + e.Source = ImGuiInputSource_Mouse; + e.MouseWheel.WheelX = wheel_x; + e.MouseWheel.WheelY = wheel_y; + g.InputEventsQueue.push_back(e); } void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) @@ -1317,14 +1345,24 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) ImGuiContext& g = *GImGui; IM_ASSERT(&g.IO == this && "Can only add events to current context."); IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT); - g.IO.MouseDown[mouse_button] = down; + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_MouseButton; + e.Source = ImGuiInputSource_Mouse; + e.MouseButton.Button = mouse_button; + e.MouseButton.Down = down; + g.InputEventsQueue.push_back(e); } void ImGuiIO::AddFocusEvent(bool focused) { - // We intentionally overwrite this and process in NewFrame(), in order to give a chance - // to multi-viewports backends to queue AddFocusEvent(false),AddFocusEvent(true) in same frame. - AppFocusLost = !focused; + ImGuiContext& g = *GImGui; + IM_ASSERT(&g.IO == this && "Can only add events to current context."); + + ImGuiInputEvent e; + e.Type = ImGuiInputEventType_Focus; + e.AppFocused.Focused = focused; + g.InputEventsQueue.push_back(e); } //----------------------------------------------------------------------------- @@ -4261,13 +4299,9 @@ void ImGui::NewFrame() //if (g.IO.AppFocusLost) // ClosePopupsExceptModals(); - // Clear buttons state when focus is lost - // (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle) - if (g.IO.AppFocusLost) - { - g.IO.ClearInputKeys(); - g.IO.AppFocusLost = false; - } + // Process input queue (trickle as many events as possible) + g.InputEventsTrail.resize(0); + UpdateInputEvents(g.IO.ConfigInputEventQueue); // Update keyboard input state UpdateKeyboardInputs(); @@ -7680,6 +7714,131 @@ static const char* GetInputSourceName(ImGuiInputSource source) } +// Process input queue +// - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost) +// - trickle_fast_inputs = true : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87) +void ImGui::UpdateInputEvents(bool trickle_fast_inputs) +{ + ImGuiContext& g = *GImGui; + ImGuiIO& io = g.IO; + + bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputed = false; + int mouse_button_changed = 0x00, key_mods_changed = 0x00; + ImBitArray key_changed_mask; + + int event_n = 0; + for (; event_n < g.InputEventsQueue.Size; event_n++) + { + const ImGuiInputEvent* e = &g.InputEventsQueue[event_n]; + if (e->Type == ImGuiInputEventType_MousePos) + { + if (io.MousePos.x != e->MousePos.PosX || io.MousePos.y != e->MousePos.PosY) + { + // Trickling Rule: Stop processing queued events if we already handled a mouse button change + if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || key_mods_changed || text_inputed)) + break; + io.MousePos = ImVec2(e->MousePos.PosX, e->MousePos.PosY); + mouse_moved = true; + } + } + else if (e->Type == ImGuiInputEventType_MouseButton) + { + const ImGuiMouseButton button = e->MouseButton.Button; + IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); + if (io.MouseDown[button] != e->MouseButton.Down) + { + // Trickling Rule: Stop processing queued events if we got multiple action on the same button + if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled)) + break; + io.MouseDown[button] = e->MouseButton.Down; + mouse_button_changed |= (1 << button); + } + } + else if (e->Type == ImGuiInputEventType_MouseWheel) + { + if (e->MouseWheel.WheelX != 0.0f || e->MouseWheel.WheelY != 0.0f) + { + // Trickling Rule: Stop processing queued events if we got multiple action on the event + if (trickle_fast_inputs && (mouse_wheeled || mouse_button_changed != 0)) + break; + io.MouseWheelH += e->MouseWheel.WheelX; + io.MouseWheel += e->MouseWheel.WheelY; + mouse_wheeled = true; + } + } + else if (e->Type == ImGuiInputEventType_Key) + { + IM_ASSERT(e->Key.Key != ImGuiKey_None); + const int keydata_index = (e->Key.Key - ImGuiKey_KeysData_OFFSET); + ImGuiKeyData* keydata = &io.KeysData[keydata_index]; + if (keydata->Down != e->Key.Down) + { + // Trickling Rule: Stop processing queued events if we got multiple action on the same button + if (trickle_fast_inputs && (key_changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0)) + break; + keydata->Down = e->Key.Down; + key_changed = true; + key_changed_mask.SetBit(keydata_index); + } + } + else if (e->Type == ImGuiInputEventType_KeyMods) + { + const ImGuiKeyModFlags modifiers = e->KeyMods.Mods; + if (io.KeyMods != modifiers) + { + // Trickling Rule: Stop processing queued events if we got multiple action on the same button + ImGuiKeyModFlags modifiers_that_are_changing = (io.KeyMods ^ modifiers); + if (trickle_fast_inputs && (key_mods_changed & modifiers_that_are_changing) != 0) + break; + io.KeyMods = modifiers; + io.KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0; + io.KeyShift = (modifiers & ImGuiKeyModFlags_Shift) != 0; + io.KeyAlt = (modifiers & ImGuiKeyModFlags_Alt) != 0; + io.KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0; + key_mods_changed |= modifiers_that_are_changing; + } + } + else if (e->Type == ImGuiInputEventType_Char) + { + // Trickling Rule: Stop processing queued events if keys/mouse have been interacted with + if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled)) + break; + unsigned int c = e->Text.Char; + io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); + text_inputed = true; + } + else if (e->Type == ImGuiInputEventType_Focus) + { + // We intentionally overwrite this and process lower, in order to give a chance + // to multi-viewports backends to queue AddFocusEvent(false) + AddFocusEvent(true) in same frame. + io.AppFocusLost = !e->AppFocused.Focused; + } + else + { + IM_ASSERT(0 && "Unknown event!"); + } + } + + // Record trail (for domain-specific applications wanting to access a precise trail) + for (int n = 0; n < event_n; n++) + g.InputEventsTrail.push_back(g.InputEventsQueue[n]); + + // Remaining events will be processed on the next frame + if (event_n == g.InputEventsQueue.Size) + g.InputEventsQueue.resize(0); + else + g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n); + + // Clear buttons state when focus is lost + // (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle) + if (g.IO.AppFocusLost) + { + g.IO.ClearInputKeys(); + g.IO.AppFocusLost = false; + } +} + + //----------------------------------------------------------------------------- // [SECTION] ERROR CHECKING //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index e7b9091ad..580af603f 100644 --- a/imgui.h +++ b/imgui.h @@ -65,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.87 WIP" -#define IMGUI_VERSION_NUM 18607 +#define IMGUI_VERSION_NUM 18608 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -1944,6 +1944,7 @@ struct ImGuiIO // Miscellaneous options bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. + bool ConfigInputEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5c5bc3a39..9b894c4bd 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -460,8 +460,10 @@ void ImGui::ShowDemoWindow(bool* p_open) } ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility."); + ImGui::Checkbox("io.ConfigInputEventQueue", &io.ConfigInputEventQueue); + ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates."); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); - ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)"); + ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)."); ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText); ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving)."); ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); diff --git a/imgui_internal.h b/imgui_internal.h index bff1a61fa..5cc7a4d4d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -199,8 +199,10 @@ namespace ImStb // Debug Logging for selected systems. Remove the '((void)0) //' to enable. //#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log //#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log +//#define IMGUI_DEBUG_LOG_IO IMGUI_DEBUG_LOG // Enable log #define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log #define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log +#define IMGUI_DEBUG_LOG_IO(...) ((void)0) // Disable log // Static Asserts #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") @@ -896,6 +898,19 @@ enum ImGuiPlotType ImGuiPlotType_Histogram }; +enum ImGuiInputEventType +{ + ImGuiInputEventType_None = 0, + ImGuiInputEventType_MousePos, + ImGuiInputEventType_MouseWheel, + ImGuiInputEventType_MouseButton, + ImGuiInputEventType_Key, + ImGuiInputEventType_KeyMods, + ImGuiInputEventType_Char, + ImGuiInputEventType_Focus, + ImGuiInputEventType_COUNT +}; + enum ImGuiInputSource { ImGuiInputSource_None = 0, @@ -907,6 +922,34 @@ enum ImGuiInputSource ImGuiInputSource_COUNT }; +// FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension? +// Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor' +struct ImGuiInputEventMousePos { float PosX, PosY; }; +struct ImGuiInputEventMouseWheel { float WheelX, WheelY; }; +struct ImGuiInputEventMouseButton { int Button; bool Down; }; +struct ImGuiInputEventKey { ImGuiKey Key; bool Down; }; +struct ImGuiInputEventKeyMods { ImGuiKeyModFlags Mods; }; +struct ImGuiInputEventText { unsigned int Char; }; +struct ImGuiInputEventAppFocused { bool Focused; }; + +struct ImGuiInputEvent +{ + ImGuiInputEventType Type; + ImGuiInputSource Source; + union + { + ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos + ImGuiInputEventMouseWheel MouseWheel; // if Type == ImGuiInputEventType_MouseWheel + ImGuiInputEventMouseButton MouseButton; // if Type == ImGuiInputEventType_MouseButton + ImGuiInputEventKey Key; // if Type == ImGuiInputEventType_Key + ImGuiInputEventKeyMods KeyMods; // if Type == ImGuiInputEventType_Modifiers + ImGuiInputEventText Text; // if Type == ImGuiInputEventType_Text + ImGuiInputEventAppFocused AppFocused; // if Type == ImGuiInputEventType_Focus + }; + + ImGuiInputEvent() { memset(this, 0, sizeof(*this)); } +}; + // FIXME-NAV: Clarify/expose various repeat delay/rate enum ImGuiInputReadMode { @@ -1498,6 +1541,8 @@ struct ImGuiContext bool Initialized; bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; + ImVector InputEventsQueue; // Input events which will be tricked/written into IO structure. + ImVector InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail. ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. @@ -2453,6 +2498,7 @@ namespace ImGui IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). // NewFrame + IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs); IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); IMGUI_API void UpdateMouseMovingWindowNewFrame(); From 90a6961638e3a7244d89969390427e5d94e856f1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Jan 2022 18:10:51 +0100 Subject: [PATCH 12/12] IO: apply same flooring as UpdateMouseInputs() in dupe event processing. (#4858) + provision for test engine. --- imgui.cpp | 9 ++++++--- imgui_internal.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 40d014bd0..8a58f8acb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3946,7 +3946,7 @@ static void ImGui::UpdateMouseInputs() // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well) if (IsMousePosValid(&io.MousePos)) - io.MousePos = g.MouseLastValidPos = ImFloor(io.MousePos); + io.MousePos = g.MouseLastValidPos = ImFloorSigned(io.MousePos); // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev)) @@ -7732,12 +7732,15 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) const ImGuiInputEvent* e = &g.InputEventsQueue[event_n]; if (e->Type == ImGuiInputEventType_MousePos) { - if (io.MousePos.x != e->MousePos.PosX || io.MousePos.y != e->MousePos.PosY) + ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY); + if (IsMousePosValid(&event_pos)) + event_pos = ImVec2(ImFloorSigned(event_pos.x), ImFloorSigned(event_pos.y)); // Apply same flooring as UpdateMouseInputs() + if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y) { // Trickling Rule: Stop processing queued events if we already handled a mouse button change if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || key_mods_changed || text_inputed)) break; - io.MousePos = ImVec2(e->MousePos.PosX, e->MousePos.PosY); + io.MousePos = event_pos; mouse_moved = true; } } diff --git a/imgui_internal.h b/imgui_internal.h index 5cc7a4d4d..62900be66 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -441,6 +441,7 @@ static inline float ImInvLength(const ImVec2& lhs, float fail_value) static inline float ImFloor(float f) { return (float)(int)(f); } static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } +static inline ImVec2 ImFloorSigned(const ImVec2& v) { return ImVec2(ImFloorSigned(v.x), ImFloorSigned(v.y)); } static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } @@ -936,6 +937,7 @@ struct ImGuiInputEvent { ImGuiInputEventType Type; ImGuiInputSource Source; + bool SubmittedByTestEngine; union { ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos