From 81e0be856a6273c414c456a64fd28879fe81bf45 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 14:27:43 +0100 Subject: [PATCH 01/11] Fixed strict-aliasing violation in FormatTextureIDForDebugDisplay(). (#7090, #7256) --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 75050e35..4cb27b55 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14787,10 +14787,12 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) { + union { void* ptr; int integer; } tex_id_opaque; + memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id))); if (sizeof(tex_id) >= sizeof(void*)) - ImFormatString(buf, buf_size, "0x%p", (void*)*(intptr_t*)(void*)&tex_id); + ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr); else - ImFormatString(buf, buf_size, "0x%04X", *(int*)(void*)&tex_id); + ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer); } // [DEBUG] Display contents of ImDrawList From 1ce41f6218d00d6855b08400ea6c04f78b2ace5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Gallet?= Date: Mon, 22 Jan 2024 17:51:24 +0100 Subject: [PATCH 02/11] Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) Amended with (bd->GlVersion >= 210) checks. --- backends/imgui_impl_opengl3.cpp | 12 ++++++++++++ backends/imgui_impl_opengl3_loader.h | 2 ++ docs/CHANGELOG.txt | 1 + 3 files changed, 15 insertions(+) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index a36a7ac2..1c63641a 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -191,6 +191,11 @@ #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif +// Desktop GL and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. +#if !defined(IMGUI_IMPL_OPENGL_ES2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK +#endif + // Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART @@ -747,6 +752,10 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() GLint last_texture, last_array_buffer; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK + GLint last_pixel_unpack_buffer; + if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } +#endif #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -920,6 +929,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() // Restore modified GL state glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK + if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); } +#endif #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array); #endif diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index 85c58c4e..4019f937 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -260,6 +260,8 @@ typedef khronos_intptr_t GLintptr; #define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_STREAM_DRAW 0x88E0 +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c1313218..204dff22 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,7 @@ Other changes: - Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] +- Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) ----------------------------------------------------------------------- From 1509842107dcded1a596ae1c24e7d74300c65555 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 15:15:15 +0100 Subject: [PATCH 03/11] Backends: OpenGL3: Shallow tweak of compile-time extensions detection. Detect polygon mode using same method as others (not define/symbol). IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS -> IMGUI_IMPL_OPENGL_HAS_EXTENSIONS --- backends/imgui_impl_glfw.cpp | 4 +--- backends/imgui_impl_opengl3.cpp | 40 +++++++++++++++------------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index b49c99bb..a968fe30 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -114,7 +114,7 @@ enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, - GlfwClientApi_Vulkan + GlfwClientApi_Vulkan, }; struct ImGui_ImplGlfw_Data @@ -674,11 +674,9 @@ static void ImGui_ImplGlfw_UpdateMouseData() ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) { GLFWwindow* window = bd->Window; - #ifdef __EMSCRIPTEN__ const bool is_window_focused = true; #else diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 1c63641a..b3a510bc 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -176,22 +176,13 @@ #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #endif -// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. -#ifdef GL_POLYGON_MODE -#define IMGUI_IMPL_HAS_POLYGON_MODE -#endif - -// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET -#endif - -// Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() -#if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER +// Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have.. +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) +#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS) +#define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has glPolygonMode() #endif -// Desktop GL and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. +// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. #if !defined(IMGUI_IMPL_OPENGL_ES2) #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK #endif @@ -201,9 +192,14 @@ #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #endif -// Desktop GL use extension detection -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS +// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET +#endif + +// Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() +#if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif // [Debugging] @@ -364,7 +360,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Detect extensions we support bd->HasClipOrigin = (bd->GlVersion >= 450); -#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS +#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS GLint num_extensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); for (GLint i = 0; i < num_extensions; i++) @@ -416,7 +412,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid if (bd->GlVersion >= 310) glDisable(GL_PRIMITIVE_RESTART); #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif @@ -505,7 +501,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); #endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); @@ -644,7 +640,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif -#ifdef IMGUI_IMPL_HAS_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { @@ -655,7 +651,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } -#endif // IMGUI_IMPL_HAS_POLYGON_MODE +#endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); From 9176eedf24070649db23ea59d4174bcf6281b640 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 17:47:30 +0100 Subject: [PATCH 04/11] Internals: SetShortcutRouting() move code so next commit is easier to read. Should be no-op. --- imgui.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4cb27b55..8177e104 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8438,17 +8438,20 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI return true; } - // Specific culling for shortcuts with no modifiers when there's an active id. - // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. - // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. - // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. - // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) - if ((flags & ImGuiInputFlags_RouteFocused) && (g.ActiveId != 0 && g.ActiveId != owner_id)) - if (g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) + // Specific culling when there's an active. + if (g.ActiveId != 0 && g.ActiveId != owner_id) + { + // Cull shortcuts with no modifiers when it could generate a character. + // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. + // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. + // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. + // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) + if ((flags & ImGuiInputFlags_RouteFocused) && g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) { IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); return false; } + } // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); From 8491cf36adb2663f16975bc4ebcd871daf5ff8b7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jan 2024 17:52:46 +0100 Subject: [PATCH 05/11] Inputs: g.ActiveIdUsingManyKeys[] prevent routes from being claimed. Amend fc134f5 --- imgui.cpp | 10 ++++++++++ imgui.h | 2 +- imgui_internal.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8177e104..768cf950 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8451,6 +8451,16 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); return false; } + + // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId + if ((flags & ImGuiInputFlags_RouteGlobalHigh) == 0 && g.ActiveIdUsingAllKeyboardKeys) + { + ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + if (key == ImGuiKey_None) + key = ConvertSingleModFlagToKey(&g, (ImGuiKey)(key_chord & ImGuiMod_Mask_)); + if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END) + return false; + } } // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. diff --git a/imgui.h b/imgui.h index 88df9491..56b3455e 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19015 +#define IMGUI_VERSION_NUM 19016 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 786ea68e..840b9a04 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1461,7 +1461,7 @@ enum ImGuiInputFlags_ ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority. ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). - ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overiden by this) + ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this) ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. // Routing polices: extra options ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. From f1960b60c1ae129e401c6582080ea9e6dfcf0b00 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Thu, 25 Jan 2024 10:16:27 +0000 Subject: [PATCH 06/11] Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) There are two issues here - first, this macro uses AT&T specific syntax with $, which is not necessary. Also, some assemblers (nasm) emit different bytes for "int 3" and "int3", so it's better to use "int3" (cd 03 vs cc) More importantly, GDB has some failing assertion whenever stepping after hitting an "int3" instruction. This makes it practically useless, as is. For some reason, putting a nop afterwards as a workaround is okay. Related discussions: https://sourceware.org/bugzilla/show_bug.cgi?id=31194 https://lists.sr.ht/~skeeto/public-inbox/%3C2d3d7662a361ddd049f7dc65b94cecdd%40disroot.org%3E --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 204dff22..c6d0f0bf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other changes: - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. +- Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] - Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois] - Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) diff --git a/imgui_internal.h b/imgui_internal.h index 840b9a04..c256ec22 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -300,11 +300,11 @@ namespace ImStb #elif defined(__clang__) #define IM_DEBUG_BREAK() __builtin_debugtrap() #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03") +#define IM_DEBUG_BREAK() __asm__ volatile("int3;nop") #elif defined(__GNUC__) && defined(__thumb__) #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01") #elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) -#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0"); +#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0") #else #define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! #endif From 719475637095a2794a2385856abb300e00afc761 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jan 2024 12:48:04 +0100 Subject: [PATCH 07/11] Shortcut: fixed single mod-key Shortcut from working e.g. Shortcut(ImGuiKey_LeftCtrl) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 34 ++++++++++++++++++++++++++-------- imgui_internal.h | 3 ++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c6d0f0bf..7278ddb7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,8 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) +- Internals: Various improvements related to yet unpublicized shortcut routing and input ownerhip + systems. ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 768cf950..040e6712 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8115,6 +8115,26 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // - Shortcut() [Internal] //----------------------------------------------------------------------------- +ImGuiKeyChord ImGui::FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord) +{ + // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. + ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + if (IsModKey(key)) + { + if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl) + key_chord |= ImGuiMod_Ctrl; + if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift) + key_chord |= ImGuiMod_Shift; + if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt) + key_chord |= ImGuiMod_Alt; + if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper) + key_chord |= ImGuiMod_Super; + } + if (key_chord & ImGuiMod_Shortcut) + return (key_chord & ~ImGuiMod_Shortcut) | (ctx->IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); + return key_chord; +} + ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; @@ -8198,8 +8218,7 @@ const char* ImGui::GetKeyName(ImGuiKey key) const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "", @@ -8420,8 +8439,8 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None); - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. + key_chord = FixupKeyChord(&g, key_chord); // [DEBUG] Debug break requested by user if (g.DebugBreakInShortcutRouting == key_chord) @@ -8489,9 +8508,9 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI // Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id) { + ImGuiContext& g = *GImGui; const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry. return routing_data->RoutingCurr == routing_id; } @@ -9422,8 +9441,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord) bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; - if (key_chord & ImGuiMod_Shortcut) - key_chord = ConvertShortcutMod(key_chord); + key_chord = FixupKeyChord(&g, key_chord); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); if (g.IO.KeyMods != mods) return false; diff --git a/imgui_internal.h b/imgui_internal.h index c256ec22..f26ebcea 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3159,7 +3159,8 @@ namespace ImGui inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } - inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); } + inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } + ImGuiKeyChord FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord); inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; From 96839b445e32e46d87a44fd43a9cdd60c806f7e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jan 2024 15:43:19 +0100 Subject: [PATCH 08/11] Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on indiviudal left/right alt key without intefering with the other. See test "inputs_owner_single_mod" --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 27 ++++++++++++++++----------- imgui_internal.h | 2 ++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7278ddb7..5ec7a2ed 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,8 @@ Other changes: - Nav: Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope, regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz] - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) +- Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on + indiviudal left/right alt key without intefering with the other. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] diff --git a/imgui.cpp b/imgui.cpp index 040e6712..8bfc66cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12627,28 +12627,33 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Press and Release ALT to toggle menu layer - // - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer. - // - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway. - if (nav_keyboard_active && IsKeyPressed(ImGuiMod_Alt, ImGuiKeyOwner_None)) - { - g.NavWindowingToggleLayer = true; - g.NavInputSource = ImGuiInputSource_Keyboard; - } + const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt }; + for (ImGuiKey windowing_toggle_key : windowing_toggle_keys) + if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, ImGuiKeyOwner_None)) + { + g.NavWindowingToggleLayer = true; + g.NavWindowingToggleKey = windowing_toggle_key; + g.NavInputSource = ImGuiInputSource_Keyboard; + break; + } if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard) { // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370) // We cancel toggling nav layer when other modifiers are pressed. (See #4439) + // - AltGR is Alt+Ctrl on some layout but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). // We cancel toggling nav layer if an owner has claimed the key. - if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) == false) + if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper) + g.NavWindowingToggleLayer = false; + if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_None) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) == false) g.NavWindowingToggleLayer = false; - // Apply layer toggle on release + // Apply layer toggle on Alt release // Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss. - if (IsKeyReleased(ImGuiMod_Alt) && g.NavWindowingToggleLayer) + if (IsKeyReleased(g.NavWindowingToggleKey) && g.NavWindowingToggleLayer) if (g.ActiveId == 0 || g.ActiveIdAllowOverlap) if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev)) apply_toggle_layer = true; - if (!IsKeyDown(ImGuiMod_Alt)) + if (!IsKeyDown(g.NavWindowingToggleKey)) g.NavWindowingToggleLayer = false; } diff --git a/imgui_internal.h b/imgui_internal.h index f26ebcea..92507062 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2078,6 +2078,7 @@ struct ImGuiContext float NavWindowingTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; + ImGuiKey NavWindowingToggleKey; ImVec2 NavWindowingAccumDeltaPos; ImVec2 NavWindowingAccumDeltaSize; @@ -2329,6 +2330,7 @@ struct ImGuiContext NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; + NavWindowingToggleKey = ImGuiKey_None; DimBgRatio = 0.0f; From 6172c22c5dc751c617ca51c3ca72cc62472e9449 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 1 Feb 2024 22:07:29 +0700 Subject: [PATCH 09/11] CI: Update to `actions/checkout` `v4` from `v3`. (#7281) --- .github/workflows/build.yml | 12 ++++++------ .github/workflows/static-analysis.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c77e9a8c..d332903e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\ MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies shell: powershell @@ -209,7 +209,7 @@ jobs: Linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -402,7 +402,7 @@ jobs: MacOS: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -462,7 +462,7 @@ jobs: iOS: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build example_apple_metal run: | @@ -472,7 +472,7 @@ jobs: Emscripten: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -499,7 +499,7 @@ jobs: Android: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build example_android_opengl3 run: | diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index caa9b3a4..69df5cdf 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -12,7 +12,7 @@ jobs: PVS-Studio: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 From f50ddc431e3b8840036e88abc4c3cf74500aa12b Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 2 Feb 2024 00:30:00 +0700 Subject: [PATCH 10/11] Fixed some typos. (#7282) --- backends/imgui_impl_allegro5.cpp | 2 +- backends/imgui_impl_opengl2.cpp | 2 +- docs/CHANGELOG.txt | 2 +- docs/FONTS.md | 2 +- imgui_draw.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index abb6b9ad..ef1f13f3 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -27,7 +27,7 @@ // 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. +// 2021-12-08: Renderer: Fixed mishandling of 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). // 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 0d703769..17935b1f 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -23,7 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. -// 2021-12-08: OpenGL: 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-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. // 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). // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) // 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5ec7a2ed..1625bdc8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,7 +68,7 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) -- Internals: Various improvements related to yet unpublicized shortcut routing and input ownerhip +- Internals: Various improvements related to yet unpublicized shortcut routing and input ownership systems. diff --git a/docs/FONTS.md b/docs/FONTS.md index cbf13e13..df8b610e 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -53,7 +53,7 @@ All loaded fonts glyphs are rendered into a single texture atlas ahead of time. This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty black or white rectangle.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. Some solutions: -- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality looss. +- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality loss. Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample). - Reduce glyphs ranges by calculating them from source localization data. You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win! diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9008eb74..a40ce168 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -641,7 +641,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; } -// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). +// Release the number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). void ImDrawList::PrimUnreserve(int idx_count, int vtx_count) { IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); From 06ce312745e0b25bfa8412b324503393964e3812 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Feb 2024 21:35:47 +0100 Subject: [PATCH 11/11] InputText: Internal: added reload from user-buf feature. (#2890) Very highly requested feature (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968). Also useful for interactive completion/selection popups (#2057, #718) Based on @kudaba PR. Design for Inputtext V2 should make this obsolete. --- docs/CHANGELOG.txt | 6 ++++-- imgui.cpp | 2 ++ imgui.h | 2 +- imgui_internal.h | 13 +++++++++++++ imgui_widgets.cpp | 16 ++++++++++++---- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1625bdc8..88d79421 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,8 +68,10 @@ Other changes: update stopped setting default values. (#7232) [@GrigoryGraborenko] - Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya] - Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) -- Internals: Various improvements related to yet unpublicized shortcut routing and input ownership - systems. +- Internals: Many improvements related to yet unpublicized shortcut routing and input ownership systems. +- Internals: InputText: Add way to force reload of user-buf when active. (#2890) [@kudaba, @ocornut] + Often requested in some form (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968), + and useful for interactive completion/suggestions popups (#2057, #718) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 8bfc66cb..7493fd4a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12257,6 +12257,8 @@ void ImGui::NavMoveRequestApplyResult() g.NavWindow = result->Window; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; } + + // FIXME: Could become optional e.g. ImGuiNavMoveFlags_NoClearActiveId if we later want to apply navigation requests without altering active input. if (g.ActiveId != result->ID) ClearActiveID(); diff --git a/imgui.h b/imgui.h index 56b3455e..f8971ad1 100644 --- a/imgui.h +++ b/imgui.h @@ -24,7 +24,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.2 WIP" -#define IMGUI_VERSION_NUM 19016 +#define IMGUI_VERSION_NUM 19017 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 92507062..fb6b7a22 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1079,6 +1079,9 @@ struct IMGUI_API ImGuiInputTextState bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool Edited; // edited this frame ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set. + bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version. + int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet. + int ReloadSelectionEnd; ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } @@ -1096,6 +1099,16 @@ struct IMGUI_API ImGuiInputTextState int GetSelectionStart() const { return Stb.select_start; } int GetSelectionEnd() const { return Stb.select_end; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } + + // Reload user buf (WIP #2890) + // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) + // strcpy(my_buf, "hello"); + // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item + // state->ReloadUserBufAndSelectAll(); + void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } + void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; } + void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } + }; enum ImGuiNextWindowDataFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 93cfa38f..ba4d3f5b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4185,14 +4185,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; + const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_state = (init_make_active || user_scroll_active); - if ((init_state && g.ActiveId != id) || init_changed_specs) + if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf) { // Access state even if we don't own it yet. state = &g.InputTextState; state->CursorAnimReset(); + state->ReloadUserBuf = false; // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) InputTextDeactivateHook(state->ID); @@ -4204,8 +4206,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ memcpy(state->InitialTextA.Data, buf, buf_len + 1); // Preserve cursor position and undo/redo stack if we come back to same widget - // FIXME: Since we reworked this on 2022/06, may want to differenciate recycle_cursor vs recycle_undostate? - bool recycle_state = (state->ID == id && !init_changed_specs); + // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? + bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf); if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0))) recycle_state = false; @@ -4230,7 +4232,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ stb_textedit_initialize_state(&state->Stb, !is_multiline); } - if (!is_multiline) + if (init_reload_from_user_buf) + { + state->Stb.select_start = state->ReloadSelectionStart; + state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd; + state->CursorClamp(); + } + else if (!is_multiline) { if (flags & ImGuiInputTextFlags_AutoSelectAll) select_all = true;