Merge branch 'ocornut:master' into sdl_cpu

This commit is contained in:
MoonPower
2026-03-13 14:50:16 +01:00
committed by GitHub
11 changed files with 126 additions and 36 deletions
+1 -1
View File
@@ -274,7 +274,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
{ {
// Create and upload new texture to graphics system // Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height); //IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr); IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32); IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
const void* pixels = tex->GetPixels(); const void* pixels = tex->GetPixels();
GLuint gl_texture_id = 0; GLuint gl_texture_id = 0;
+1 -1
View File
@@ -744,7 +744,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
{ {
// Create and upload new texture to graphics system // Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height); //IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr); IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32); IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
const void* pixels = tex->GetPixels(); const void* pixels = tex->GetPixels();
GLuint gl_texture_id = 0; GLuint gl_texture_id = 0;
+1 -1
View File
@@ -254,7 +254,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
{ {
// Create and upload new texture to graphics system // Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height); //IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr); IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32); IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
// Create texture // Create texture
+1
View File
@@ -1376,6 +1376,7 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
} }
// Update the Descriptor Set: // Update the Descriptor Set:
if (descriptor_set != VK_NULL_HANDLE)
{ {
VkDescriptorImageInfo desc_image[1] = {}; VkDescriptorImageInfo desc_image[1] = {};
desc_image[0].sampler = sampler; desc_image[0].sampler = sampler;
+21
View File
@@ -41,6 +41,16 @@ HOW TO UPDATE?
Breaking Changes: Breaking Changes:
- Changed default ImTextureID_Invalid value to -1 instead of 0 if not #define-d.
(#9293, #8745, #8465, #7090)
- It seems like a better default since it will work with backends storing
indices or memory offsets inside ImTextureID, where 0 might be a valid value.
- If this is causing problem with e.g your custom ImTextureID definition, you can
add '#define ImTextureID_Invalid 0' to your imconfig.h + PLEASE report this to GitHub.
- If you have hardcoded e.g. 'if (tex_id == 0)' checks they should be updated.
e.g. OpenGL2, OpenGL3 and SDLRenderer3 backends incorrectly had 'IM_ASSERT(tex->TexID == 0)'
lines which were replaced with 'IM_ASSERT(tex->TexID == ImTextureID_Invalid)'.
If you have copied or forked backends consider fixing locally. (#9295)
- Separator(): fixed a legacy quirk where Separator() was submitting a zero-height - Separator(): fixed a legacy quirk where Separator() was submitting a zero-height
item for layout purpose, even though it draws a 1-pixel separator. item for layout purpose, even though it draws a 1-pixel separator.
The fix could affect code e.g. computing height from multiple widgets in order to The fix could affect code e.g. computing height from multiple widgets in order to
@@ -72,6 +82,9 @@ Other Changes:
- InputText: - InputText:
- Shift+Enter in multi-line editor always adds a new line, regardless of - Shift+Enter in multi-line editor always adds a new line, regardless of
ImGuiInputTextFlags_CtrlEnterForNewLine being set or not. (#9239) ImGuiInputTextFlags_CtrlEnterForNewLine being set or not. (#9239)
- Reworked io.ConfigInputTextEnterKeepActive mode so that pressing Enter will
deactivate/reactivate the item in order for e.g. IsItemDeactivatedAfterEdit()
signals to be emitted the same way regardless of that setting. (#9001, #9115)
- Style: - Style:
- Border sizes are now scaled (and rounded) by ScaleAllSizes(). - Border sizes are now scaled (and rounded) by ScaleAllSizes().
- When using large values with ScallAllSizes(), the following items thickness - When using large values with ScallAllSizes(), the following items thickness
@@ -81,6 +94,10 @@ Other Changes:
- TextLink() underline thickness. - TextLink() underline thickness.
- ColorButton() border thickness. - ColorButton() border thickness.
- Separator() thickness, via scaling newly added style.SeparatorSize. (#2657, #9263) - Separator() thickness, via scaling newly added style.SeparatorSize. (#2657, #9263)
- Nav:
- Popups: Shift+F10 or Menu key can now open popups menus when using
BeginPopupContextItem(), BeginPopupContextWindow() or OpenPopupOnItemClick().
(#8803, #9270) [@exelix11, @ocornut]
- Clipper: - Clipper:
- Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false. - Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false.
- Added `UserIndex` helper storage. This is solely a convenience for cases where - Added `UserIndex` helper storage. This is solely a convenience for cases where
@@ -89,6 +106,8 @@ Other Changes:
- Implemented a custom tweak to extend hit-testing bounding box when window is sitting - Implemented a custom tweak to extend hit-testing bounding box when window is sitting
at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the
mouse at the extreme of the screen will reach the scrollbar. (#9276) mouse at the extreme of the screen will reach the scrollbar. (#9276)
- Focus: fixed fallback "Debug" window temporarily taking focus and setting io.WantCaptureKeyboard
for one frame on e.g. application boot if no other windows are submitted. (#9243)
- Demo: fixed IMGUI_DEMO_MARKER locations for examples applets. (#9261, #3689) [@pthom] - Demo: fixed IMGUI_DEMO_MARKER locations for examples applets. (#9261, #3689) [@pthom]
- Backends: - Backends:
- SDLGPU3: removed unnecessary call to SDL_WaitForGPUIdle when releasing - SDLGPU3: removed unnecessary call to SDL_WaitForGPUIdle when releasing
@@ -104,6 +123,8 @@ Other Changes:
- hidden scrollbar in Firefox. - hidden scrollbar in Firefox.
- Vulkan: added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying - Vulkan: added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying
extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej] extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej]
- Vulkan: ImGui_ImplVulkan_AddTexture() skips updating descriptor_set if failing
to allocate one. (#8677) [@micb25]
- WebGPU: fixed undefined behaviors in example code for requesting adapter - WebGPU: fixed undefined behaviors in example code for requesting adapter
and device. (#9246, #9256) [@r-lyeh] and device. (#9246, #9256) [@r-lyeh]
- GLFW/SDL2/SDL3+WebGPU: removed suport for Emscripten <4.0.10. (#9281) [@ypujante] - GLFW/SDL2/SDL3+WebGPU: removed suport for Emscripten <4.0.10. (#9281) [@ypujante]
+5 -5
View File
@@ -55,8 +55,8 @@ if (ImGui::Button("Save"))
ImGui::InputText("string", buf, IM_COUNTOF(buf)); ImGui::InputText("string", buf, IM_COUNTOF(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
``` ```
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" /> <img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" /> <img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
```cpp ```cpp
// Create a window called "My First Tool", with a menu bar. // Create a window called "My First Tool", with a menu bar.
@@ -150,10 +150,10 @@ Officially maintained backends (in repository):
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets. - Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages. - Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
<img width="878" height="220" alt="Useful extensions" src="https://github.com/user-attachments/assets/e6b0aa7c-bf53-41c5-ac69-bea3098b1dee" />
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page: [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
[![Useful extensions thumbnails](https://github.com/user-attachments/assets/e6b0aa7c-bf53-41c5-ac69-bea3098b1dee)](https://github.com/ocornut/imgui/wiki/Useful-Extensions)
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot), [ImPlot3d](https://github.com/brenocq/implot3d) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
+72 -16
View File
@@ -167,6 +167,7 @@ CODE
- Home, End Scroll to top, scroll to bottom. - Home, End Scroll to top, scroll to bottom.
- Alt Toggle between scrolling layer and menu layer. - Alt Toggle between scrolling layer and menu layer.
- Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving. - Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving.
- Menu or Shift+F10 Open context menu.
- Output when ImGuiConfigFlags_NavEnableKeyboard set, - Output when ImGuiConfigFlags_NavEnableKeyboard set,
- io.WantCaptureKeyboard flag is set when keyboard is claimed. - io.WantCaptureKeyboard flag is set when keyboard is claimed.
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
@@ -394,6 +395,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2026/03/12 (1.92.7) - Changed default ImTextureID_Invalid to -1 instead of 0 if not #define-d. (#9293, #8745, #8465, #7090)
It seems like a better default since it will work with backends storing indices or memory offsets inside ImTextureID, where 0 might be a valid value.
If this is causing problem with e.g. your custom ImTextureID definition, you can add '#define ImTextureID_Invalid 0' to your imconfig.h + PLEASE report this to GitHub.
If you have hard-coded e.g. 'if (tex_id == 0)' checks they should be updated. e.g. OpenGL2, OpenGL3 and SDLRenderer3 backends incorrectly had 'IM_ASSERT(tex->TexID == 0)' lines which were replaced with 'IM_ASSERT(tex->TexID == ImTextureID_Invalid)'. (#9295)
- 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator. - 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator.
The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263) The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
The "Console" example had such a bug: The "Console" example had such a bug:
@@ -402,8 +407,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
Should be: Should be:
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing(); float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
BeginChild("ScrollingRegion", { 0, -footer_height }); BeginChild("ScrollingRegion", { 0, -footer_height });
When such idiom was used and assuming zero-height Separator, it is likely that When such idiom was used and assuming zero-height Separator, it is likely that in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
- 2026/02/23 (1.92.7) - Commented out legacy signature for Combo(), ListBox(), signatures which were obsoleted in 1.90 (Nov 2023), when the getter callback type was changed. - 2026/02/23 (1.92.7) - Commented out legacy signature for Combo(), ListBox(), signatures which were obsoleted in 1.90 (Nov 2023), when the getter callback type was changed.
- Old getter type: bool (*getter)(void* user_data, int idx, const char** out_text) // Set label + return bool. False replaced label with placeholder. - Old getter type: bool (*getter)(void* user_data, int idx, const char** out_text) // Set label + return bool. False replaced label with placeholder.
- New getter type: const char* (*getter)(void* user_data, int idx) // Return label or NULL/empty label if missing - New getter type: const char* (*getter)(void* user_data, int idx) // Return label or NULL/empty label if missing
@@ -1355,6 +1359,7 @@ static void NavUpdateWindowing();
static void NavUpdateWindowingApplyFocus(ImGuiWindow* window); static void NavUpdateWindowingApplyFocus(ImGuiWindow* window);
static void NavUpdateWindowingOverlay(); static void NavUpdateWindowingOverlay();
static void NavUpdateCancelRequest(); static void NavUpdateCancelRequest();
static void NavUpdateContextMenuRequest();
static void NavUpdateCreateMoveRequest(); static void NavUpdateCreateMoveRequest();
static void NavUpdateCreateTabbingRequest(); static void NavUpdateCreateTabbingRequest();
static float NavUpdatePageUpPageDown(); static float NavUpdatePageUpPageDown();
@@ -4212,6 +4217,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
NavWindow = NULL; NavWindow = NULL;
NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
NavOpenContextMenuItemId = NavOpenContextMenuWindowId = 0;
NavNextActivateId = 0; NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0; NavHighlightActivatedId = 0;
@@ -4281,6 +4287,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
InputTextPasswordFontBackupFlags = ImFontFlags_None; InputTextPasswordFontBackupFlags = ImFontFlags_None;
InputTextReactivateId = 0;
TempInputId = 0; TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue)); memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0; BeginMenuDepth = BeginComboDepth = 0;
@@ -5572,6 +5579,8 @@ void ImGui::NewFrame()
g.ActiveIdIsJustActivated = false; g.ActiveIdIsJustActivated = false;
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
g.TempInputId = 0; g.TempInputId = 0;
if (g.InputTextReactivateId != 0 && g.InputTextReactivateId != g.DeactivatedItemData.ID)
g.InputTextReactivateId = 0;
if (g.ActiveId == 0) if (g.ActiveId == 0)
{ {
g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingNavDirMask = 0x00;
@@ -5982,10 +5991,14 @@ void ImGui::EndFrame()
} }
g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0; g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0;
// Hide implicit/fallback "Debug" window if it hasn't been used // Hide and unfocus implicit/fallback "Debug" window if it hasn't been used
g.WithinFrameScopeWithImplicitWindow = false; g.WithinFrameScopeWithImplicitWindow = false;
if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) if (g.CurrentWindow && g.CurrentWindow->IsFallbackWindow && g.CurrentWindow->WriteAccessed == false)
{
g.CurrentWindow->Active = false; g.CurrentWindow->Active = false;
if (g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow)
FocusWindow(NULL);
}
End(); End();
// Update navigation: Ctrl+Tab, wrap-around requests // Update navigation: Ctrl+Tab, wrap-around requests
@@ -12489,17 +12502,40 @@ ImGuiMouseButton ImGui::GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags)
return ImGuiMouseButton_Right; // Default == 1 return ImGuiMouseButton_Right; // Default == 1
} }
bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
return true;
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
return true;
return false;
}
bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
return true;
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
if (IsWindowChildOf(g.NavWindow, g.CurrentWindow, false)) // This enable ordering to be used to disambiguate item vs window (#8803)
return true;
return false;
}
// Helper to open a popup if mouse button is released over the item // Helper to open a popup if mouse button is released over the item
// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
{ {
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
OpenPopupEx(id, popup_flags); OpenPopupEx(id, popup_flags);
} }
} }
@@ -12526,10 +12562,9 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems) if (window->SkipItems)
return false; return false;
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItem ID. Using LastItem ID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
OpenPopupEx(id, popup_flags); OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
} }
@@ -12541,10 +12576,8 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl
if (!str_id) if (!str_id)
str_id = "window_context"; str_id = "window_context";
ImGuiID id = window->GetID(str_id); ImGuiID id = window->GetID(str_id);
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); if (IsPopupOpenRequestForWindow(popup_flags))
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) OpenPopupEx(id, popup_flags);
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
} }
@@ -13721,6 +13754,7 @@ static void ImGui::NavUpdate()
// Process NavCancel input (to close a popup, get back to parent, clear focus) // Process NavCancel input (to close a popup, get back to parent, clear focus)
NavUpdateCancelRequest(); NavUpdateCancelRequest();
NavUpdateContextMenuRequest();
// Process manual activation request // Process manual activation request
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0; g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
@@ -14205,6 +14239,28 @@ static void ImGui::NavUpdateCancelRequest()
} }
} }
static void ImGui::NavUpdateContextMenuRequest()
{
ImGuiContext& g = *GImGui;
g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
if (!nav_keyboard_active || g.NavWindow == NULL)
return;
const bool request = IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner) || (IsKeyPressed(ImGuiKey_F10, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner) && g.IO.KeyMods == ImGuiMod_Shift);
if (!request)
return;
g.NavOpenContextMenuItemId = g.NavId;
g.NavOpenContextMenuWindowId = g.NavWindow->ID;
// Allow triggering for Begin()..BeginPopupContextItem(). A possible alternative would be to use g.NavLayer == ImGuiNavLayer_Menu.
if (g.NavId == g.NavWindow->GetID("#CLOSE") || g.NavId == g.NavWindow->GetID("#COLLAPSE"))
g.NavOpenContextMenuItemId = g.NavWindow->MoveId;
g.NavInputSource = ImGuiInputSource_Keyboard;
SetNavCursorVisibleAfterMove();
}
// Handle PageUp/PageDown/Home/End keys // Handle PageUp/PageDown/Home/End keys
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request // Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference // FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
+10 -6
View File
@@ -30,7 +30,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.7 WIP" #define IMGUI_VERSION "1.92.7 WIP"
#define IMGUI_VERSION_NUM 19264 #define IMGUI_VERSION_NUM 19265
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -340,9 +340,11 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that. typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
#endif #endif
// Define this if you need 0 to be a valid ImTextureID for your backend. // Define this if you need to change the invalid value for your backend.
// - in v1.92.7 (2025/03/12): we changed default value from 0 to -1 as it is a better default, which supports storing offsets/indices.
// - If this is causing problem with your custom ImTextureID definition, you can add '#define ImTextureID_Invalid' to your imconfig + please report this to GitHub.
#ifndef ImTextureID_Invalid #ifndef ImTextureID_Invalid
#define ImTextureID_Invalid ((ImTextureID)0) #define ImTextureID_Invalid ((ImTextureID)-1)
#endif #endif
// ImTextureRef = higher-level identifier for a texture. Store a ImTextureID _or_ a ImTextureData*. // ImTextureRef = higher-level identifier for a texture. Store a ImTextureID _or_ a ImTextureData*.
@@ -2428,7 +2430,7 @@ struct ImGuiIO
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
@@ -3906,8 +3908,10 @@ inline ImTextureID ImTextureRef::GetTexID() const
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too) // Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
inline ImTextureID ImDrawCmd::GetTexID() const inline ImTextureID ImDrawCmd::GetTexID() const
{ {
// If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92) // If you are getting this assert with ImTextureID_Invalid == 0 and your ImTextureID is used to store an index:
// must iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. // - You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig file.
// If you are getting this assert with a renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92+):
// - You must correctly iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. See docs/BACKENDS.md.
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above. ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
if (TexRef._TexData != NULL) if (TexRef._TexData != NULL)
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!"); IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
+2 -1
View File
@@ -526,7 +526,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)."); ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive); ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only)."); ImGui::SameLine(); HelpMarker("Pressing Enter will reactivate item and select all text (single-line only).");
ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText); ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving)."); ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors); ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
@@ -8738,6 +8738,7 @@ void ImGui::ShowUserGuide()
BulletText("Return to input text into a widget."); BulletText("Return to input text into a widget.");
BulletText("Escape to deactivate a widget, close popup,\nexit a child window or the menu layer, clear focus."); BulletText("Escape to deactivate a widget, close popup,\nexit a child window or the menu layer, clear focus.");
BulletText("Alt to jump to the menu layer of a window."); BulletText("Alt to jump to the menu layer of a window.");
BulletText("Menu or Shift+F10 to open a context menu.");
Unindent(); Unindent();
} }
+5
View File
@@ -2332,6 +2332,8 @@ struct ImGuiContext
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavHighlightActivatedId; ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer; float NavHighlightActivatedTimer;
ImGuiID NavOpenContextMenuItemId;
ImGuiID NavOpenContextMenuWindowId;
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame. ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
@@ -2461,6 +2463,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFontBaked InputTextPasswordFontBackupBaked; ImFontBaked InputTextPasswordFontBackupBaked;
ImFontFlags InputTextPasswordFontBackupFlags; ImFontFlags InputTextPasswordFontBackupFlags;
ImGuiID InputTextReactivateId; // ID of InputText to reactivate on next frame (for io.ConfigInputTextEnterKeepActive behavior)
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc. ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth; int BeginMenuDepth;
@@ -3330,6 +3333,8 @@ namespace ImGui
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags); IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
IMGUI_API bool IsPopupOpenRequestForItem(ImGuiPopupFlags flags, ImGuiID id);
IMGUI_API bool IsPopupOpenRequestForWindow(ImGuiPopupFlags flags);
// Tooltips // Tooltips
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags); IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
+7 -5
View File
@@ -4761,7 +4761,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
wrap_width = ImMax(1.0f, GetContentRegionAvail().x + (draw_window->ScrollbarY ? 0.0f : -g.Style.ScrollbarSize)); wrap_width = ImMax(1.0f, GetContentRegionAvail().x + (draw_window->ScrollbarY ? 0.0f : -g.Style.ScrollbarSize));
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard))); const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
const bool input_requested_by_reactivate = (g.InputTextReactivateId == id); // for io.ConfigInputTextEnterKeepActive
const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_clicked = hovered && io.MouseClicked[0];
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
@@ -4772,7 +4772,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf); const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state. 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_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_reactivate);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if (init_reload_from_user_buf) if (init_reload_from_user_buf)
{ {
@@ -5109,11 +5109,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
bool is_new_line = is_multiline && !is_gamepad_validate && (is_shift_enter || (is_enter && !ctrl_enter_for_new_line) || (is_ctrl_enter && ctrl_enter_for_new_line)); bool is_new_line = is_multiline && !is_gamepad_validate && (is_shift_enter || (is_enter && !ctrl_enter_for_new_line) || (is_ctrl_enter && ctrl_enter_for_new_line));
if (!is_new_line) if (!is_new_line)
{ {
validated = true; validated = clear_active_id = true;
if (io.ConfigInputTextEnterKeepActive && !is_multiline) if (io.ConfigInputTextEnterKeepActive && !is_multiline)
{
// Queue reactivation, so that e.g. IsItemDeactivatedAfterEdit() will work. (#9001)
state->SelectAll(); // No need to scroll state->SelectAll(); // No need to scroll
else g.InputTextReactivateId = id; // Mark for reactivation on next frame
clear_active_id = true; }
} }
else if (!is_readonly) else if (!is_readonly)
{ {