From b2e2cc44c2a77e94bbf9d401449cf221dc5b8443 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Jan 2022 15:47:37 +0100 Subject: [PATCH 01/11] Backends: OSX: Fixed typo. --- backends/imgui_impl_osx.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 64984bd349d8..df94b95c01ff 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -656,7 +656,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) { io.AddKeyEvent(key, (imgui_flags & imgui_mask) != 0); } - io.SetKeyEventNativeData(key, keycode, -1); // To support legacy indexing (<1.87 user code) + io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code) } return io.WantCaptureKeyboard; From e8172fdfbc003ba28b93905db980f384092faf86 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Jan 2022 16:59:31 +0100 Subject: [PATCH 02/11] Rename io.AddKeyModEvent() -> io.AddKeyModsEvent() and updated backends accordingly. (#2625, #4858) Amend 790132a (breaking) --- 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 | 4 ++-- backends/imgui_impl_sdl.cpp | 5 ++--- backends/imgui_impl_win32.cpp | 4 ++-- docs/CHANGELOG.txt | 2 +- imgui.cpp | 4 ++-- imgui.h | 2 +- 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index ae50485fecad..68615160246f 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -17,7 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). @@ -570,7 +570,7 @@ void ImGui_ImplAllegro5_NewFrame() ((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.AddKeyModEvent(key_mods); + io.AddKeyModsEvent(key_mods); ImGui_ImplAllegro5_UpdateMouseCursor(); } diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp index 1eb7a585abcf..fdf482fc9a22 100644 --- a/backends/imgui_impl_android.cpp +++ b/backends/imgui_impl_android.cpp @@ -19,7 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. #include "imgui.h" @@ -292,7 +292,7 @@ void ImGui_ImplAndroid_NewFrame() io.SetKeyEventNativeData(key_event.Key, key_event.NativeKeycode, key_event.NativeScancode); // To support legacy indexing (<1.87 user code) key_queue.second.pop(); } - io.AddKeyModEvent(g_KeyModFlags); + io.AddKeyModsEvent(g_KeyModFlags); // Setup display size (every frame to accommodate for window resizing) int32_t window_width = ANativeWindow_getWidth(g_Window); diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index d3276724821c..8485a9b03e68 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,7 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. // 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback(). // 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback(). @@ -549,7 +549,7 @@ static void ImGui_ImplGlfw_UpdateKeyModifiers() (((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.AddKeyModEvent(key_mods); + io.AddKeyModsEvent(key_mods); } void ImGui_ImplGlfw_NewFrame() diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index 68e417f2da30..6eec280e33c4 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. @@ -210,7 +210,7 @@ static void ImGui_ImplGLUT_UpdateKeyboardMods() ((glut_key_mods & GLUT_ACTIVE_CTRL) ? ImGuiKeyModFlags_Ctrl : 0) | ((glut_key_mods & GLUT_ACTIVE_SHIFT) ? ImGuiKeyModFlags_Shift : 0) | ((glut_key_mods & GLUT_ACTIVE_ALT) ? ImGuiKeyModFlags_Alt : 0); - io.AddKeyModEvent(key_mods); + io.AddKeyModsEvent(key_mods); } static void ImGui_ImplGLUT_AddKeyEvent(ImGuiKey key, bool down, int native_keycode) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index df94b95c01ff..4ef44c5fc354 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -22,7 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. // 2021-12-13: Add game controller support. // 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards. @@ -496,7 +496,7 @@ static void ImGui_ImplOSX_UpdateGamepads() static void ImGui_ImplOSX_UpdateKeyModifiers() { ImGuiIO& io = ImGui::GetIO(); - io.AddKeyModEvent(g_KeyModifiers); + io.AddKeyModsEvent(g_KeyModifiers); } void ImGui_ImplOSX_NewFrame(NSView* view) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 0d4d7ef0ee1d..78451346a3ea 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,7 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST. // 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+) // 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary. @@ -510,8 +510,7 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers() ((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.AddKeyModEvent(key_mods); - + io.AddKeyModsEvent(key_mods); } void ImGui_ImplSDL2_NewFrame() diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 5eb6d2bc5308..039558d64323 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -33,7 +33,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. +// 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. // 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. @@ -235,7 +235,7 @@ static void ImGui_ImplWin32_UpdateKeyModifiers() ((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); - io.AddKeyModEvent(key_mods); + io.AddKeyModsEvent(key_mods); } static void ImGui_ImplWin32_UpdateMousePos() diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3153a670c99e..a780c9e6517a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,7 +39,7 @@ Breaking Changes: - Reworked IO keyboard input system. (#2625, #3724) [@thedmd, @ocornut] - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. - - Added io.AddKeyModEvent() function, obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. + - 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. - Added full range of key enums in ImGuiKey (e.g. ImGuiKey_F1). - Added GetKeyName() helper function. diff --git a/imgui.cpp b/imgui.cpp index ee47182f327f..dc51a320c719 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -390,7 +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() - - inputs: added io.AddKeyModEvent() instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper. + - 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'. - 2022/01/01 (1.87) - commented out redirecting functions/enums names that were marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019) @@ -1282,7 +1282,7 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native #endif } -void ImGuiIO::AddKeyModEvent(ImGuiKeyModFlags modifiers) +void ImGuiIO::AddKeyModsEvent(ImGuiKeyModFlags modifiers) { KeyMods = modifiers; KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0; diff --git a/imgui.h b/imgui.h index 444d02889622..064ff3b85aa8 100644 --- a/imgui.h +++ b/imgui.h @@ -2007,7 +2007,7 @@ 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 AddKeyModEvent(ImGuiKeyModFlags modifiers); // Queue a change of Ctrl/Shift/Alt/Super modifiers + IMGUI_API void AddKeyModsEvent(ImGuiKeyModFlags modifiers);// Queue a change of Ctrl/Shift/Alt/Super modifiers 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 From 956e03009a56efad0681db7a5450a37105afc89d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 11 Jan 2022 16:13:38 +0100 Subject: [PATCH 03/11] Backends: OSX: Build fIx. Made GetKeyName() input tolerant. Internals: added GetNavInputName(). --- backends/imgui_impl_osx.mm | 3 ++- imgui.cpp | 14 ++++++++++++++ imgui.h | 5 ++--- imgui_internal.h | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 4ef44c5fc354..394cd0de8a2a 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -603,9 +603,10 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) if ([event isARepeat]) return io.WantCaptureKeyboard; + int key_code = (int)[event keyCode]; ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code); io.AddKeyEvent(key, event.type == NSEventTypeKeyDown); - io.SetKeyEventNativeData(key, (int)[event keyCode], -1); // To support legacy indexing (<1.87 user code) + io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code) return io.WantCaptureKeyboard; } diff --git a/imgui.cpp b/imgui.cpp index dc51a320c719..aa24c118626c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7435,6 +7435,8 @@ const char* ImGui::GetKeyName(ImGuiKey key) #endif if (key == ImGuiKey_None) return "None"; + if (!IsNamedKey(key)) + return "Unknown"; return GKeyNames[key - ImGuiKey_NamedKey_BEGIN]; } @@ -9717,6 +9719,18 @@ static ImVec2 ImGui::NavCalcPreferredRefPos() } } +const char* ImGui::GetNavInputName(ImGuiNavInput n) +{ + static const char* names[] = + { + "Activate", "Cancel", "Input", "Menu", "DpadLeft", "DpadRight", "DpadUp", "DpadDown", "LStickLeft", "LStickRight", "LStickUp", "LStickDown", + "FocusPrev", "FocusNext", "TweakSlow", "TweakFast", "KeyLeft", "KeyRight", "KeyUp", "KeyDown" + }; + IM_ASSERT(IM_ARRAYSIZE(names) == ImGuiNavInput_COUNT); + IM_ASSERT(n >= 0 && n < ImGuiNavInput_COUNT); + return names[n]; +} + float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 064ff3b85aa8..2775a0f3f65b 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 18604 +#define IMGUI_VERSION_NUM 18605 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -1523,8 +1523,7 @@ enum ImGuiNavInput_ ImGuiNavInput_KeyRight_, // Move right ImGuiNavInput_KeyUp_, // Move up ImGuiNavInput_KeyDown_, // Move down - ImGuiNavInput_COUNT, - ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyLeft_ + ImGuiNavInput_COUNT }; // Configuration flags stored in io.ConfigFlags. Set by user/application. diff --git a/imgui_internal.h b/imgui_internal.h index d725c90f90d2..80fd75d55956 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2577,6 +2577,7 @@ namespace ImGui IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); + IMGUI_API const char* GetNavInputName(ImGuiNavInput n); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); From 96186a93b9233b04717f63668cb0c406e260a151 Mon Sep 17 00:00:00 2001 From: Bertie Wheen Date: Wed, 12 Jan 2022 13:12:25 +0000 Subject: [PATCH 04/11] Typo correction in imgui_demo.cpp (#4892) --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 589a92a9cbd8..7e96811e7f5f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -5997,7 +5997,7 @@ void ImGui::ShowAboutWindow(bool* p_open) namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); } // Demo helper function to select among loaded fonts. -// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one. +// Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one. void ImGui::ShowFontSelector(const char* label) { ImGuiIO& io = ImGui::GetIO(); From 0818a423962e4fa85200227c0558a0a5034d1114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 11 Jan 2022 22:56:35 +0100 Subject: [PATCH 05/11] Backend: WebGPU: Fixed incorrect size parameters in WGPU backend (#4891) + squash SDL alignment bits. --- backends/imgui_impl_sdl.cpp | 12 ++++++------ backends/imgui_impl_wgpu.cpp | 4 ++-- docs/CHANGELOG.txt | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 78451346a3ea..bb09a7e71ced 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -231,7 +231,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) switch (event->type) { - case SDL_MOUSEWHEEL: + case SDL_MOUSEWHEEL: { if (event->wheel.x > 0) io.MouseWheelH += 1; if (event->wheel.x < 0) io.MouseWheelH -= 1; @@ -239,27 +239,27 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) if (event->wheel.y < 0) io.MouseWheel -= 1; return true; } - case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONDOWN: { if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; } if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; } if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; } return true; } - case SDL_TEXTINPUT: + case SDL_TEXTINPUT: { io.AddInputCharactersUTF8(event->text.text); return true; } - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_KEYDOWN: + case SDL_KEYUP: { 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. return true; } - case SDL_WINDOWEVENT: + case SDL_WINDOWEVENT: { if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 072f25497340..6e12c6f43484 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -314,8 +314,8 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1); // Bind shader and vertex buffers - wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize); - wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize); + wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert)); + wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx)); wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState); wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a780c9e6517a..f39c69de4c16 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,6 +104,8 @@ Other Changes: Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file. - 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: WebGPU: Fixed incorrect size parameters in wgpuRenderPassEncoderSetIndexBuffer() and + wgpuRenderPassEncoderSetVertexBuffer() calls. (#4891) [@FeepsDev] ----------------------------------------------------------------------- From 290c51735ecf1d470116c7aeeebe3cef33be2583 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Jan 2022 14:18:34 +0100 Subject: [PATCH 06/11] Fixed warning in ImFloorSigned(). (#4889) --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 80fd75d55956..88e09851eb03 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -441,7 +441,7 @@ static inline float ImLengthSqr(const ImVec2& lhs) static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; } static inline float ImFloor(float f) { return (float)(int)(f); } -static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() +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 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; } From 457d4b7b72606663f588fe28103bf9e725f9ecfa Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Wed, 12 Jan 2022 14:30:04 +0100 Subject: [PATCH 07/11] Backends: OSX: Adedd basic IME support for macOS. (#3108, #2598) --- backends/imgui_impl_osx.h | 3 ++- backends/imgui_impl_osx.mm | 52 +++++++++++++++++++++++++++++++++++++- docs/CHANGELOG.txt | 1 + 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 37851a3c3aea..859061920f1c 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -7,7 +7,8 @@ // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. - +// [X] Platform: IME support. +// // 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. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 394cd0de8a2a..55f269d18722 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -7,6 +7,7 @@ // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [X] Platform: IME support. // 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. @@ -22,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 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. // 2021-12-13: Add game controller support. @@ -54,6 +56,7 @@ static ImGuiKeyModFlags g_KeyModifiers = ImGuiKeyModFlags_None; static ImFocusObserver* g_FocusObserver = nil; static KeyEventResponder* g_KeyEventResponder = nil; +static NSTextInputContext* g_InputContext = nil; // Undocumented methods for creating cursors. @interface NSCursor() @@ -91,6 +94,29 @@ @interface KeyEventResponder: NSView @end @implementation KeyEventResponder +{ + float _posX; + float _posY; + NSRect _imeRect; +} + +#pragma mark - Public + +- (void)setImePosX:(float)posX imePosY:(float)posY +{ + _posX = posX; + _posY = posY; +} + +- (void)updateImePosWithView:(NSView *)view +{ + NSWindow *window = view.window; + if (!window) + return; + NSRect contentRect = [window contentRectForFrameRect:window.frame]; + NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0); + _imeRect = [window convertRectToScreen:rect]; +} - (void)viewDidMoveToWindow { @@ -145,7 +171,7 @@ - (NSUInteger)characterIndexForPoint:(NSPoint)point - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange { - return NSZeroRect; + return _imeRect; } - (BOOL)hasMarkedText @@ -390,6 +416,7 @@ bool ImGui_ImplOSX_Init(NSView* view) // Add the NSTextInputClient to the view hierarchy, // to receive keyboard events and translate them to input text. g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; + g_InputContext = [[NSTextInputContext alloc] initWithClient:g_KeyEventResponder]; [view addSubview:g_KeyEventResponder]; // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down). @@ -401,6 +428,21 @@ bool ImGui_ImplOSX_Init(NSView* view) return event; }]; + io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void + { + if (data->WantVisible) + { + [g_InputContext activate]; + } + else + { + [g_InputContext discardMarkedText]; + [g_InputContext invalidateCharacterCoordinates]; + [g_InputContext deactivate]; + } + [g_KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight]; + }; + return true; } @@ -499,6 +541,13 @@ static void ImGui_ImplOSX_UpdateKeyModifiers() io.AddKeyModsEvent(g_KeyModifiers); } +static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view) +{ + ImGuiIO& io = ImGui::GetIO(); + if (io.WantTextInput) + [g_KeyEventResponder updateImePosWithView:view]; +} + void ImGui_ImplOSX_NewFrame(NSView* view) { // Setup display size @@ -523,6 +572,7 @@ void ImGui_ImplOSX_NewFrame(NSView* view) ImGui_ImplOSX_UpdateKeyModifiers(); ImGui_ImplOSX_UpdateMouseCursorAndButtons(); ImGui_ImplOSX_UpdateGamepads(); + ImGui_ImplOSX_UpdateImePosWithView(view); } bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f39c69de4c16..5fbf9a113bea 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,6 +104,7 @@ Other Changes: Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file. - 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: WebGPU: Fixed incorrect size parameters in wgpuRenderPassEncoderSetIndexBuffer() and wgpuRenderPassEncoderSetVertexBuffer() calls. (#4891) [@FeepsDev] From 7f8a89c25c5a2d42b4246173f4a288202fd75741 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Jan 2022 16:11:10 +0100 Subject: [PATCH 08/11] Backends: Win32, SDL: maintain MouseButtonsDown instead of using IsAnyMouseDown(). Internals: added GetInputSourceName(). --- backends/imgui_impl_sdl.cpp | 17 +++++++++++++---- backends/imgui_impl_win32.cpp | 8 ++++++-- docs/CHANGELOG.txt | 1 + imgui.cpp | 14 ++++++++++---- imgui.h | 2 +- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index bb09a7e71ced..8e61e861b735 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-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. // 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST. // 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+) @@ -74,6 +75,7 @@ struct ImGui_ImplSDL2_Data { SDL_Window* Window; Uint64 Time; + int MouseButtonsDown; bool MousePressed[3]; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; char* ClipboardTextData; @@ -240,10 +242,17 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) return true; } case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { - if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; } - if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; } - if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; } + int mouse_button = -1; + if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } + if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } + 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; + bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button)); return true; } case SDL_TEXTINPUT: @@ -409,7 +418,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons() mouse_window = focused_window; // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE); + SDL_CaptureMouse(bd->MouseButtonsDown != 0 ? SDL_TRUE : SDL_FALSE); #else // SDL 2.0.3 and non-windowed systems: single-viewport only SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL; diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 039558d64323..12f602f85930 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -33,6 +33,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 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. // 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. @@ -74,6 +75,7 @@ struct ImGui_ImplWin32_Data HWND hWnd; HWND MouseHwnd; bool MouseTracked; + int MouseButtonsDown; INT64 Time; INT64 TicksPerSecond; ImGuiMouseCursor LastMouseCursor; @@ -531,9 +533,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + if (bd->MouseButtonsDown == 0 && ::GetCapture() == NULL) ::SetCapture(hwnd); io.MouseDown[button] = true; + bd->MouseButtonsDown |= 1 << button; return 0; } case WM_LBUTTONUP: @@ -547,7 +550,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA if (msg == WM_MBUTTONUP) { button = 2; } if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } io.MouseDown[button] = false; - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + bd->MouseButtonsDown &= ~(1 << button); + if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) ::ReleaseCapture(); return 0; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5fbf9a113bea..4582e489f52f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -97,6 +97,7 @@ 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: SDL: Pass localized keys (matching keyboard layout). Fix e.g. CTRL+A, CTRL+Z, CTRL+Y shortcuts. +- Backends: Win32, 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: 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. diff --git a/imgui.cpp b/imgui.cpp index aa24c118626c..c963db4ed9ac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7585,6 +7585,7 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; } +// [WILL OBSOLETE] This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid. bool ImGui::IsAnyMouseDown() { ImGuiContext& g = *GImGui; @@ -7642,6 +7643,13 @@ void ImGui::CaptureMouseFromApp(bool capture) g.WantCaptureMouseNextFrame = capture ? 1 : 0; } +static const char* GetInputSourceName(ImGuiInputSource source) +{ + const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" }; + IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT); + return input_source_names[source]; +} + //----------------------------------------------------------------------------- // [SECTION] ERROR CHECKING @@ -12107,8 +12115,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Misc Details if (TreeNode("Internal state")) { - const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); - Text("WINDOWING"); Indent(); Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); @@ -12119,7 +12125,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("ITEMS"); Indent(); - Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); + Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, GetInputSourceName(g.ActiveIdSource)); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); int active_id_using_key_input_count = 0; @@ -12134,7 +12140,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Indent(); Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); - Text("NavInputSource: %s", input_source_names[g.NavInputSource]); + Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource)); Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId); Text("NavActivateFlags: %04X", g.NavActivateFlags); diff --git a/imgui.h b/imgui.h index 2775a0f3f65b..a1cfb769408b 100644 --- a/imgui.h +++ b/imgui.h @@ -908,7 +908,7 @@ namespace ImGui IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0). IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available - IMGUI_API bool IsAnyMouseDown(); // is any mouse button held? + IMGUI_API bool IsAnyMouseDown(); // [WILL OBSOLETE] is any mouse button held? This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid. IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves) IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) From bf4de2a46b689f9aafd0211b2e1da29fcc7780d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Jan 2022 16:29:20 +0100 Subject: [PATCH 09/11] Backends: Win32: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured + update MousePos before Key Modifiers. --- backends/imgui_impl_win32.cpp | 57 +++++++++++++++++------------------ docs/CHANGELOG.txt | 4 ++- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 12f602f85930..bd3d54784156 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -18,6 +18,7 @@ #define WIN32_LEAN_AND_MEAN #endif #include +#include // GET_X_LPARAM(), GET_Y_LPARAM() #include #include @@ -33,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-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-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. @@ -240,38 +242,31 @@ static void ImGui_ImplWin32_UpdateKeyModifiers() io.AddKeyModsEvent(key_mods); } -static void ImGui_ImplWin32_UpdateMousePos() +static void ImGui_ImplWin32_UpdateMouseData() { ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(bd->hWnd != 0); - const ImVec2 mouse_pos_prev = io.MousePos; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - - // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing) - HWND focused_window = ::GetForegroundWindow(); - HWND hovered_window = bd->MouseHwnd; - HWND mouse_window = NULL; - if (hovered_window && (hovered_window == bd->hWnd || ::IsChild(hovered_window, bd->hWnd))) - mouse_window = hovered_window; - else if (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd))) - mouse_window = focused_window; - if (mouse_window == NULL) - return; - - // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) - if (io.WantSetMousePos) + const bool is_app_focused = (::GetForegroundWindow() == bd->hWnd); + if (is_app_focused) { - POINT pos = { (int)mouse_pos_prev.x, (int)mouse_pos_prev.y }; - if (::ClientToScreen(bd->hWnd, &pos)) - ::SetCursorPos(pos.x, pos.y); - } + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + { + POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; + if (::ClientToScreen(bd->hWnd, &pos)) + ::SetCursorPos(pos.x, pos.y); + } - // Set Dear ImGui mouse position from OS position - POINT pos; - if (::GetCursorPos(&pos) && ::ScreenToClient(mouse_window, &pos)) - io.MousePos = ImVec2((float)pos.x, (float)pos.y); + // (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured) + if (!io.WantSetMousePos && !bd->MouseTracked) + { + POINT pos; + if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) + io.MousePos = ImVec2((float)pos.x, (float)pos.y); + } + } } // Gamepad navigation mapping @@ -341,15 +336,15 @@ void ImGui_ImplWin32_NewFrame() io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; bd->Time = current_time; + // Update OS mouse position + ImGui_ImplWin32_UpdateMouseData(); + // Process workarounds for known Windows key handling issues ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); // Update key modifiers ImGui_ImplWin32_UpdateKeyModifiers(); - // Update OS mouse position - ImGui_ImplWin32_UpdateMousePos(); - // Update OS mouse cursor with the cursor requested by imgui ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (bd->LastMouseCursor != mouse_cursor) @@ -517,11 +512,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)); break; case WM_MOUSELEAVE: if (bd->MouseHwnd == hwnd) bd->MouseHwnd = NULL; bd->MouseTracked = false; + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: @@ -535,8 +532,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } if (bd->MouseButtonsDown == 0 && ::GetCapture() == NULL) ::SetCapture(hwnd); - io.MouseDown[button] = true; bd->MouseButtonsDown |= 1 << button; + io.MouseDown[button] = true; return 0; } case WM_LBUTTONUP: @@ -549,10 +546,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA if (msg == WM_RBUTTONUP) { button = 1; } if (msg == WM_MBUTTONUP) { button = 2; } if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } - io.MouseDown[button] = false; bd->MouseButtonsDown &= ~(1 << button); if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) ::ReleaseCapture(); + io.MouseDown[button] = false; return 0; } case WM_MOUSEWHEEL: diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4582e489f52f..e9b8e70010c3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -96,8 +96,10 @@ 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: 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: Win32, SDL: Maintain a MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. +- 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: 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. From 98ce013242050add7e891952ba0bd10f26b91a07 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Jan 2022 16:44:24 +0100 Subject: [PATCH 10/11] Backends: SDL: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured + update MousePos before MouseButtons. --- backends/imgui_impl_sdl.cpp | 81 ++++++++++++++++--------------------- docs/CHANGELOG.txt | 1 + 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 8e61e861b735..f0109547134b 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-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. // 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST. @@ -233,6 +234,11 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) switch (event->type) { + case SDL_MOUSEMOTION: + { + io.MousePos = ImVec2((float)event->motion.x, (float)event->motion.y); + return true; + } case SDL_MOUSEWHEEL: { if (event->wheel.x > 0) io.MouseWheelH += 1; @@ -270,6 +276,8 @@ 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); if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) @@ -391,61 +399,42 @@ void ImGui_ImplSDL2_Shutdown() IM_DELETE(bd); } -static void ImGui_ImplSDL2_UpdateMousePosAndButtons() +static void ImGui_ImplSDL2_UpdateMouseData() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - ImVec2 mouse_pos_prev = io.MousePos; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - - // Update mouse buttons - int mouse_x_local, mouse_y_local; - Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local); - 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; - - // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing) + // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - SDL_Window* focused_window = SDL_GetKeyboardFocus(); - SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH. - SDL_Window* mouse_window = NULL; - if (hovered_window && bd->Window == hovered_window) - mouse_window = hovered_window; - else if (focused_window && bd->Window == focused_window) - mouse_window = focused_window; - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside SDL_CaptureMouse(bd->MouseButtonsDown != 0 ? SDL_TRUE : SDL_FALSE); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); + const bool is_app_focused = (bd->Window == focused_window); #else - // SDL 2.0.3 and non-windowed systems: single-viewport only - SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL; + const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only #endif - - if (mouse_window == NULL) - return; - - // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) - if (io.WantSetMousePos) - SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y); - - // Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior) - if (bd->MouseCanUseGlobalState) - { - // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) - // Unlike local position obtained earlier this will be valid when straying out of bounds. - int mouse_x_global, mouse_y_global; - SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); - int window_x, window_y; - SDL_GetWindowPosition(mouse_window, &window_x, &window_y); - io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); - } - else + if (is_app_focused) { - io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local); + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); + + // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + { + 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); + io.MousePos = ImVec2((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() @@ -545,10 +534,8 @@ 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; - // Update key modifiers ImGui_ImplSDL2_UpdateKeyModifiers(); - - ImGui_ImplSDL2_UpdateMousePosAndButtons(); + ImGui_ImplSDL2_UpdateMouseData(); ImGui_ImplSDL2_UpdateMouseCursor(); // Update game controllers (if enabled and available) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e9b8e70010c3..f9eb46b21223 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -99,6 +99,7 @@ Other Changes: - 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: 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: OpenGL3: Fixed a buffer overflow in imgui_impl_opengl3_loader.h init (added in 1.86). (#4468, #4830) [@dymk] From 200a8f1ea21010c92f45428dc958d04b803ff5cd Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Jan 2022 17:08:37 +0100 Subject: [PATCH 11/11] Backends: GLFW: Update mouse inputs using glfwSetCursorPosCallback() (breaking) + fallback to provide it when focused but not hovered/captured + update MousePos before MouseButtons. + Allegro5 remove unnecessary clear. --- backends/imgui_impl_allegro5.cpp | 2 - backends/imgui_impl_glfw.cpp | 67 +++++++++++++++++++------------- backends/imgui_impl_glfw.h | 5 ++- docs/CHANGELOG.txt | 5 +++ 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 68615160246f..ac03b3c1ef4a 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -414,8 +414,6 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) }; bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - #if ALLEGRO_HAS_CLIPBOARD io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText; diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 8485a9b03e68..de6301dca232 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-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. // 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback(). @@ -90,6 +91,7 @@ struct ImGui_ImplGlfw_Data // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. GLFWwindowfocusfun PrevUserCallbackWindowFocus; + GLFWcursorposfun PrevUserCallbackCursorPos; GLFWcursorenterfun PrevUserCallbackCursorEnter; GLFWmousebuttonfun PrevUserCallbackMousebutton; GLFWscrollfun PrevUserCallbackScroll; @@ -307,16 +309,30 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) io.AddFocusEvent(focused != 0); } +void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) +{ + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + if (bd->PrevUserCallbackCursorPos != NULL && window == bd->Window) + bd->PrevUserCallbackCursorPos(window, x, y); + + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2((float)x, (float)y); +} + void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window) bd->PrevUserCallbackCursorEnter(window, entered); + ImGuiIO& io = ImGui::GetIO(); if (entered) bd->MouseWindow = window; if (!entered && bd->MouseWindow == window) + { bd->MouseWindow = NULL; + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + } } void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) @@ -394,6 +410,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->InstalledCallbacks = true; bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback); bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback); + bd->PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback); bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); @@ -430,6 +447,7 @@ void ImGui_ImplGlfw_Shutdown() { glfwSetWindowFocusCallback(bd->Window, bd->PrevUserCallbackWindowFocus); glfwSetCursorEnterCallback(bd->Window, bd->PrevUserCallbackCursorEnter); + glfwSetCursorPosCallback(bd->Window, bd->PrevUserCallbackCursorPos); glfwSetMouseButtonCallback(bd->Window, bd->PrevUserCallbackMousebutton); glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll); glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey); @@ -445,39 +463,36 @@ void ImGui_ImplGlfw_Shutdown() IM_DELETE(bd); } -static void ImGui_ImplGlfw_UpdateMousePosAndButtons() +static void ImGui_ImplGlfw_UpdateMouseData() { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - const ImVec2 mouse_pos_prev = io.MousePos; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - - // Update mouse buttons - // (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) - 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; - } - #ifdef __EMSCRIPTEN__ - const bool focused = true; + const bool is_app_focused = true; #else - const bool focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0; + const bool is_app_focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0; #endif - GLFWwindow* mouse_window = (bd->MouseWindow == bd->Window || focused) ? bd->Window : NULL; - - // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) - if (io.WantSetMousePos && focused) - glfwSetCursorPos(bd->Window, (double)mouse_pos_prev.x, (double)mouse_pos_prev.y); + if (is_app_focused) + { + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) + glfwSetCursorPos(bd->Window, (double)io.MousePos.x, (double)io.MousePos.y); + + // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured) + if (is_app_focused && bd->MouseWindow == NULL) + { + double mouse_x, mouse_y; + glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); + } + } - // Set Dear ImGui mouse position from OS position - if (mouse_window != NULL) + // Update buttons + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { - double mouse_x, mouse_y; - glfwGetCursorPos(mouse_window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); + io.MouseDown[i] = bd->MouseJustPressed[i] || glfwGetMouseButton(bd->Window, i) != 0; + bd->MouseJustPressed[i] = false; } } @@ -572,10 +587,8 @@ void ImGui_ImplGlfw_NewFrame() io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; - // Update key modifiers ImGui_ImplGlfw_UpdateKeyModifiers(); - - ImGui_ImplGlfw_UpdateMousePosAndButtons(); + ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseCursor(); // Update game controllers (if enabled and available) diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 84fa4b8bcca9..46585c0a9350 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -32,8 +32,9 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); // GLFW callbacks // - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks. -IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); -IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); +IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84 +IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84 +IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87 IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f9eb46b21223..58604c9a2964 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,10 @@ Breaking Changes: - io.AddKeyEvent() will later be turned into a trickling IO queue (for all inputs) to handle very low framerate better. (#2525, #2787, #3383) - io.SetKeyEventNativeData() include native keycode/scancode which will later be exposed. (#3141, #2959) - Renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum. (#2625) +- Backends: GLFW: backend now uses glfwSetCursorPosCallback(). + - If calling ImGui_ImplGlfw_InitXXX with install_callbacks=true: nothing to do. is already done for you. + - If calling ImGui_ImplGlfw_InitXXX with install_callbacks=false: you WILL NEED to register the GLFW callback + using glfwSetCursorPosCallback() and forward it to the backend function ImGui_ImplGlfw_CursorPosCallback(). - Commented out redirecting functions/enums names that were marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019) - ImGui::SetNextTreeNodeOpen() -> use ImGui::SetNextItemOpen() - ImGui::GetContentRegionAvailWidth() -> use ImGui::GetContentRegionAvail().x @@ -96,6 +100,7 @@ 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: Update mouse position using glfwSetCursorPosCallback() + fallback when focused but not hovered/captured. - 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.