Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_win32.cpp
#	imgui.cpp
#	imgui_demo.cpp
#	imgui_internal.h
This commit is contained in:
ocornut
2025-10-30 18:08:56 +01:00
14 changed files with 194 additions and 100 deletions

3
.gitignore vendored
View File

@@ -46,6 +46,9 @@ examples/example_glfw_opengl3/web/*
examples/example_glfw_wgpu/web/* examples/example_glfw_wgpu/web/*
examples/example_glfw_wgpu/external/* examples/example_glfw_wgpu/external/*
examples/example_sdl2_opengl3/web/* examples/example_sdl2_opengl3/web/*
examples/example_sdl2_wgpu/web/*
examples/example_sdl3_opengl3/web/*
examples/example_sdl3_wgpu/web/*
## JetBrains IDE artifacts ## JetBrains IDE artifacts
.idea .idea

View File

@@ -99,7 +99,7 @@ struct ImGui_ImplVulkan_PipelineInfo
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors. // and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you. // - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
// - About dynamic rendering: // - About dynamic rendering:
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. // - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
struct ImGui_ImplVulkan_InitInfo struct ImGui_ImplVulkan_InitInfo
{ {
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE) uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)

View File

@@ -23,6 +23,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed. // 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-06-02: [Docking] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code. // 2025-06-02: [Docking] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code.
@@ -139,7 +140,6 @@ struct ImGui_ImplWin32_Data
HMODULE XInputDLL; HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities; PFN_XInputGetCapabilities XInputGetCapabilities;
PFN_XInputGetState XInputGetState; PFN_XInputGetState XInputGetState;
DWORD XInputPacketNumber;
#endif #endif
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -421,9 +421,6 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS) if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
return; return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber)
return;
bd->XInputPacketNumber = xinput_state.dwPacketNumber;
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); } #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }

View File

@@ -47,8 +47,11 @@ Other Changes:
result in temporarily incorrect state, which would lead to bugs to side effects result in temporarily incorrect state, which would lead to bugs to side effects
in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005)
EndTable() was mistakenly restoring a wrong current table. EndTable() was mistakenly restoring a wrong current table.
- Disabled: fixed a bug when a previously enabled item that got nav focus
and then turns disabled could still be activated using keyboard. (#9036)
- InputText: when buffer is not resizable, trying to paste contents that - InputText: when buffer is not resizable, trying to paste contents that
cannot fit will now truncate text instead of ignoring the paste. (#9029) cannot fit will now truncate text to nearest UTF-8 codepoint boundaries,
instead of completely ignoring the paste. (#9029)
- InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter - InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter
keys in order to allow e.g. external Shortcut override behavior. (#9004) keys in order to allow e.g. external Shortcut override behavior. (#9004)
- InputText: when using a callback to reduce/manipulate the value of BufTextLen, - InputText: when using a callback to reduce/manipulate the value of BufTextLen,
@@ -64,6 +67,11 @@ Other Changes:
triggered by some widgets e.g. Checkbox(), Selectable() and many others, which triggered by some widgets e.g. Checkbox(), Selectable() and many others, which
cleared ActiveId at the same time as editing. (#9028) cleared ActiveId at the same time as editing. (#9028)
Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited). Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited).
- Demo: About Box: emit infos to convey when IM_ASSERT() macro is disabled,
- so users don't miss out on programming errors being reported.
- so it is included in config/build info submitted in new GitHub Issues.
- Debug Tools: fixed DebugTextEncoding() potentially reading out of bounds
if provided a trailing truncated UTF-8 sequence.
- Backends: - Backends:
- GLFW: fixed building on Linux platforms where Wayland headers - GLFW: fixed building on Linux platforms where Wayland headers
are not available. (#9024, #8969, #8921, #8920) [@jagot] are not available. (#9024, #8969, #8921, #8920) [@jagot]
@@ -76,6 +84,8 @@ Other Changes:
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified. instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
(note: examples application were not updated yet) (note: examples application were not updated yet)
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
- Examples: - Examples:
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call - GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
during surface resize. (#8381) during surface resize. (#8381)

View File

@@ -36,7 +36,7 @@ EMS =
##--------------------------------------------------------------------- ##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only) # ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=2 EMS += -s USE_SDL=3
EMS += -s DISABLE_EXCEPTION_CATCHING=1 EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1 LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1

View File

@@ -15,7 +15,8 @@
#pragma once #pragma once
//---- Define assertion handler. Defaults to calling assert(). //---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. // - If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
// - Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts

View File

@@ -1687,14 +1687,15 @@ void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
AddInputCharacter((unsigned)cp); AddInputCharacter((unsigned)cp);
} }
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) void ImGuiIO::AddInputCharactersUTF8(const char* str)
{ {
if (!AppAcceptingEvents) if (!AppAcceptingEvents)
return; return;
while (*utf8_chars != 0) const char* str_end = str + strlen(str);
while (*str != 0)
{ {
unsigned int c = 0; unsigned int c = 0;
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); str += ImTextCharFromUtf8(&c, str, str_end);
AddInputCharacter(c); AddInputCharacter(c);
} }
} }
@@ -2568,6 +2569,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
int len = lengths[*(const unsigned char*)in_text >> 3]; int len = lengths[*(const unsigned char*)in_text >> 3];
int wanted = len + (len ? 0 : 1); int wanted = len + (len ? 0 : 1);
// IMPORTANT: if in_text_end == NULL it assume we have enough space!
if (in_text_end == NULL) if (in_text_end == NULL)
in_text_end = in_text + wanted; // Max length, nulls will be taken into account. in_text_end = in_text + wanted; // Max length, nulls will be taken into account.
@@ -2727,17 +2729,29 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e
return bytes_count; return bytes_count;
} }
const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr) const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p)
{ {
while (in_text_curr > in_text_start) while (in_p > in_text_start)
{ {
in_text_curr--; in_p--;
if ((*in_text_curr & 0xC0) != 0x80) if ((*in_p & 0xC0) != 0x80)
return in_text_curr; return in_p;
} }
return in_text_start; return in_text_start;
} }
const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p)
{
if (in_text_start == in_p)
return in_text_start;
const char* prev = ImTextFindPreviousUtf8Codepoint(in_text_start, in_p);
unsigned int prev_c;
int prev_c_len = ImTextCharFromUtf8(&prev_c, prev, in_text_end);
if (prev_c != IM_UNICODE_CODEPOINT_INVALID && prev_c_len <= (int)(in_p - prev))
return in_p;
return prev;
}
int ImTextCountLines(const char* in_text, const char* in_text_end) int ImTextCountLines(const char* in_text, const char* in_text_end)
{ {
if (in_text_end == NULL) if (in_text_end == NULL)
@@ -4120,6 +4134,12 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
InputTextState.Ctx = this; InputTextState.Ctx = this;
Initialized = false; Initialized = false;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = false;
TestEngineHookItems = false;
FrameCount = 0;
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
Time = 0.0f;
memset(ContextName, 0, sizeof(ContextName));
ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None; ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
Font = NULL; Font = NULL;
@@ -4129,15 +4149,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
if (shared_font_atlas == NULL) if (shared_font_atlas == NULL)
IO.Fonts->OwnerContext = this; IO.Fonts->OwnerContext = this;
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
WithinEndChildID = 0; WithinEndChildID = 0;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = false;
GcCompactAll = false;
TestEngineHookItems = false;
TestEngine = NULL; TestEngine = NULL;
memset(ContextName, 0, sizeof(ContextName));
InputEventsNextMouseSource = ImGuiMouseSource_Mouse; InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1; InputEventsNextEventId = 1;
@@ -4172,10 +4185,10 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
ActiveIdHasBeenEditedThisFrame = false; ActiveIdHasBeenEditedThisFrame = false;
ActiveIdFromShortcut = false; ActiveIdFromShortcut = false;
ActiveIdClickOffset = ImVec2(-1, -1); ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None; ActiveIdSource = ImGuiInputSource_None;
ActiveIdDisabledId = 0; ActiveIdWindow = NULL;
ActiveIdMouseButton = -1; ActiveIdMouseButton = -1;
ActiveIdDisabledId = 0;
ActiveIdPreviousFrame = 0; ActiveIdPreviousFrame = 0;
memset(&DeactivatedItemData, 0, sizeof(DeactivatedItemData)); memset(&DeactivatedItemData, 0, sizeof(DeactivatedItemData));
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation)); memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
@@ -4190,6 +4203,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
CurrentFocusScopeId = 0; CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false; DebugShowGroupRects = false;
GcCompactAll = false;
CurrentViewport = NULL; CurrentViewport = NULL;
MouseViewport = MouseLastHoveredViewport = NULL; MouseViewport = MouseLastHoveredViewport = NULL;
@@ -4306,12 +4320,12 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
memset(LocalizationTable, 0, sizeof(LocalizationTable)); memset(LocalizationTable, 0, sizeof(LocalizationTable));
LogEnabled = false; LogEnabled = false;
LogLineFirstItem = false;
LogFlags = ImGuiLogFlags_None; LogFlags = ImGuiLogFlags_None;
LogWindow = NULL; LogWindow = NULL;
LogNextPrefix = LogNextSuffix = NULL; LogNextPrefix = LogNextSuffix = NULL;
LogFile = NULL; LogFile = NULL;
LogLinePosY = FLT_MAX; LogLinePosY = FLT_MAX;
LogLineFirstItem = false;
LogDepthRef = 0; LogDepthRef = 0;
LogDepthToExpand = LogDepthToExpandDefault = 2; LogDepthToExpand = LogDepthToExpandDefault = 2;
@@ -4564,8 +4578,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL
TabId = GetID("#TAB"); TabId = GetID("#TAB");
ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
AutoFitFramesX = AutoFitFramesY = -1;
AutoPosLastDirection = ImGuiDir_None; AutoPosLastDirection = ImGuiDir_None;
AutoFitFramesX = AutoFitFramesY = -1;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
LastFrameActive = -1; LastFrameActive = -1;
@@ -5363,26 +5377,28 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
if (g.NavWindow && g.NavWindow->Appearing) if (g.NavWindow && g.NavWindow->Appearing)
return; return;
ImGuiWindow* hovered_window = g.HoveredWindow;
// Click on empty space to focus window and start moving // Click on empty space to focus window and start moving
// (after we're done with all our widgets, so e.g. clicking on docking tab-bar which have set HoveredId already and not get us here!) // (after we're done with all our widgets, so e.g. clicking on docking tab-bar which have set HoveredId already and not get us here!)
if (g.IO.MouseClicked[0]) if (g.IO.MouseClicked[0])
{ {
// Handle the edge case of a popup being closed while clicking in its empty space. // Handle the edge case of a popup being closed while clicking in its empty space.
// If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more. // If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; ImGuiWindow* hovered_root = hovered_window ? hovered_window->RootWindow : NULL;
const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel); const bool is_closed_popup = hovered_root && (hovered_root->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(hovered_root->PopupId, ImGuiPopupFlags_AnyPopupLevel);
if (root_window != NULL && !is_closed_popup) if (hovered_window != NULL && !is_closed_popup)
{ {
StartMouseMovingWindow(g.HoveredWindow); //-V595 StartMouseMovingWindow(hovered_window); //-V595
// FIXME: In principal we might be able to call StopMouseMovingWindow() below. // FIXME: In principle we might be able to call StopMouseMovingWindow() below.
// Please note how StartMouseMovingWindow() and StopMouseMovingWindow() and not entirely symetrical, at the later doesn't clear ActiveId. // Please note how StartMouseMovingWindow() and StopMouseMovingWindow() and not entirely symetrical, at the later doesn't clear ActiveId.
// Cancel moving if clicked outside of title bar // Cancel moving if clicked outside of title bar
if (g.IO.ConfigWindowsMoveFromTitleBarOnly) if ((hovered_window->BgClickFlags & ImGuiWindowBgClickFlags_Move) == 0) // set by io.ConfigWindowsMoveFromTitleBarOnly
if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive) if (!(hovered_root->Flags & ImGuiWindowFlags_NoTitleBar) || hovered_root->DockIsActive)
if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) if (!hovered_root->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
g.MovingWindow = NULL; g.MovingWindow = NULL;
// Cancel moving if clicked over an item which was disabled or inhibited by popups // Cancel moving if clicked over an item which was disabled or inhibited by popups
@@ -5393,7 +5409,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
g.ActiveIdDisabledId = g.HoveredId; g.ActiveIdDisabledId = g.HoveredId;
} }
} }
else if (root_window == NULL && g.NavWindow != NULL) else if (hovered_window == NULL && g.NavWindow != NULL)
{ {
// Clicking on void disable focus // Clicking on void disable focus
FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal); FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
@@ -5408,8 +5424,8 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
// Find the top-most window between HoveredWindow and the top-most Modal Window. // Find the top-most window between HoveredWindow and the top-most Modal Window.
// This is where we can trim the popup stack. // This is where we can trim the popup stack.
ImGuiWindow* modal = GetTopMostPopupModal(); ImGuiWindow* modal = GetTopMostPopupModal();
bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || IsWindowAbove(g.HoveredWindow, modal)); bool hovered_window_above_modal = hovered_window && (modal == NULL || IsWindowAbove(hovered_window, modal));
ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true); ClosePopupsOverWindow(hovered_window_above_modal ? hovered_window : modal, true);
} }
} }
@@ -7076,7 +7092,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
const float grip_hover_outer_size = g.WindowsBorderHoverPadding; const float grip_hover_outer_size = g.WindowsBorderHoverPadding;
ImRect clamp_rect = visibility_rect; ImRect clamp_rect = visibility_rect;
const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar); const bool window_move_from_title_bar = !(window->BgClickFlags & ImGuiWindowBgClickFlags_Move) && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
if (window_move_from_title_bar) if (window_move_from_title_bar)
clamp_rect.Min.y -= window->TitleBarHeight; clamp_rect.Min.y -= window->TitleBarHeight;
@@ -7275,11 +7291,11 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_rect) static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_rect)
{ {
ImGuiContext& g = *GImGui;
ImVec2 size_for_clamping = window->Size; ImVec2 size_for_clamping = window->Size;
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && window->DockNodeAsHost) const bool move_from_title_bar_only = (window->BgClickFlags & ImGuiWindowBgClickFlags_Move) == 0;
if (move_from_title_bar_only && window->DockNodeAsHost)
size_for_clamping.y = ImGui::GetFrameHeight(); // Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here. size_for_clamping.y = ImGui::GetFrameHeight(); // Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here.
else if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) else if (move_from_title_bar_only && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
size_for_clamping.y = window->TitleBarHeight; size_for_clamping.y = window->TitleBarHeight;
window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
} }
@@ -8462,6 +8478,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
BeginDockableDragDropTarget(window); BeginDockableDragDropTarget(window);
} }
// Set default BgClickFlags
// This is set at the end of this function, so UpdateManualResize()/ClampWindowPos() may use last-frame value if overriden by user code.
// FIXME: The general intent is that we will later expose config options to default to enable scrolling + select scrolling mouse button.
window->BgClickFlags = g.IO.ConfigWindowsMoveFromTitleBarOnly ? ImGuiWindowBgClickFlags_None : ImGuiWindowBgClickFlags_Move;
// We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
// This is useful to allow creating context menus on title bar only, etc. // This is useful to allow creating context menus on title bar only, etc.
window->DC.WindowItemStatusFlags = ImGuiItemStatusFlags_None; window->DC.WindowItemStatusFlags = ImGuiItemStatusFlags_None;
@@ -21716,10 +21737,11 @@ void ImGui::DebugTextEncoding(const char* str)
TableSetupColumn("Glyph"); TableSetupColumn("Glyph");
TableSetupColumn("Codepoint"); TableSetupColumn("Codepoint");
TableHeadersRow(); TableHeadersRow();
const char* str_end = str + strlen(str); // As we may receive malformed UTF-8, pass an explicit end instead of relying on ImTextCharFromUtf8() assuming enough space.
for (const char* p = str; *p != 0; ) for (const char* p = str; *p != 0; )
{ {
unsigned int c; unsigned int c;
const int c_utf8_len = ImTextCharFromUtf8(&c, p, NULL); const int c_utf8_len = ImTextCharFromUtf8(&c, p, str_end);
TableNextColumn(); TableNextColumn();
Text("%d", (int)(p - str)); Text("%d", (int)(p - str));
TableNextColumn(); TableNextColumn();

View File

@@ -29,7 +29,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.5 WIP" #define IMGUI_VERSION "1.92.5 WIP"
#define IMGUI_VERSION_NUM 19242 #define IMGUI_VERSION_NUM 19243
#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
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. #define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
@@ -91,12 +91,15 @@ Index of this file:
#endif #endif
// Helper Macros // Helper Macros
// (note: compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.)
#ifndef IM_ASSERT #ifndef IM_ASSERT
#include <assert.h> #include <assert.h>
#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
#endif #endif
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
#define IM_STRINGIFY_HELPER(_EXPR) #_EXPR
#define IM_STRINGIFY(_EXPR) IM_STRINGIFY_HELPER(_EXPR) // Preprocessor idiom to stringify e.g. an integer or a macro.
// Check that version and structures layouts are matching between compiled imgui code and caller. Read comments above DebugCheckVersionAndDataLayout() for details. // Check that version and structures layouts are matching between compiled imgui code and caller. Read comments above DebugCheckVersionAndDataLayout() for details.
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
@@ -713,7 +716,7 @@ namespace ImGui
IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0);
// Widgets: Input with Keyboard // Widgets: Input with Keyboard
// - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp. // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
// - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);

View File

@@ -956,8 +956,9 @@ static void DemoWindowWidgetsBasic()
ImGui::SeparatorText("Inputs"); ImGui::SeparatorText("Inputs");
{ {
// To wire InputText() with std::string or any other custom string type, // If you want to use InputText() with std::string or any custom dynamic string type:
// see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. // - For std::string: use the wrapper in misc/cpp/imgui_stdlib.h/.cpp
// - Otherwise, see the 'Dear ImGui Demo->Widgets->Text Input->Resize Callback' for using ImGuiInputTextFlags_CallbackResize.
IMGUI_DEMO_MARKER("Widgets/Basic/InputText"); IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
static char str0[128] = "Hello, world!"; static char str0[128] = "Hello, world!";
ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
@@ -3780,8 +3781,10 @@ static void DemoWindowWidgetsTextInput()
IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input"); IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
if (ImGui::TreeNode("Multi-line Text Input")) if (ImGui::TreeNode("Multi-line Text Input"))
{ {
// Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize // WE ARE USING A FIXED-SIZE BUFFER FOR SIMPLICITY HERE.
// and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings. // If you want to use InputText() with std::string or any custom dynamic string type:
// - For std::string: use the wrapper in misc/cpp/imgui_stdlib.h/.cpp
// - Otherwise, see the 'Dear ImGui Demo->Widgets->Text Input->Resize Callback' for using ImGuiInputTextFlags_CallbackResize.
static char text[1024 * 16] = static char text[1024 * 16] =
"/*\n" "/*\n"
" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
@@ -8272,6 +8275,25 @@ void ImGui::ShowAboutWindow(bool* p_open)
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
ImGui::Text("define: IMGUI_HAS_DOCK"); ImGui::Text("define: IMGUI_HAS_DOCK");
#endif #endif
#ifdef NDEBUG
ImGui::Text("define: NDEBUG");
#endif
// Heuristic to detect no-op IM_ASSERT() macros
// - This is designed so people opening bug reports would convey and notice that they have disabled asserts for Dear ImGui code.
// - 16 is > strlen("((void)(_EXPR))") which we suggested in our imconfig.h template as a possible way to disable.
int assert_runs_expression = 0;
IM_ASSERT(++assert_runs_expression);
int assert_expand_len = (int)strlen(IM_STRINGIFY(IM_ASSERT(true)));
bool assert_maybe_disabled = (!assert_runs_expression || assert_expand_len <= 16);
ImGui::Text("IM_ASSERT: runs expression: %s. expand size: %s%s",
assert_runs_expression ? "OK" : "KO", (assert_expand_len > 16) ? "OK" : "KO", assert_maybe_disabled ? " (MAYBE DISABLED?!)" : "");
if (assert_maybe_disabled)
{
ImGui::SameLine();
HelpMarker("IM_ASSERT() calls assert() by default. Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes!");
}
ImGui::Separator(); ImGui::Separator();
ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL"); ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL"); ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");

View File

@@ -5029,7 +5029,9 @@ const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese()
void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
{ {
while (text_end ? (text < text_end) : *text) if (text_end == NULL)
text_end = text + strlen(text);
while (text < text_end)
{ {
unsigned int c = 0; unsigned int c = 0;
int c_len = ImTextCharFromUtf8(&c, text, text_end); int c_len = ImTextCharFromUtf8(&c, text, text_end);

View File

@@ -215,6 +215,7 @@ typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // F
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx() typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx() typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest() typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
typedef int ImGuiWindowBgClickFlags; // -> enum ImGuiWindowBgClickFlags_ // Flags: for overriding behavior of clicking on window background/void.
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy() typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
// Table column indexing // Table column indexing
@@ -288,8 +289,6 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // ImTrunc() is not inlined in MSVC debug builds #define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // ImTrunc() is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // #define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) //
#define IM_STRINGIFY_HELPER(_X) #_X
#define IM_STRINGIFY(_X) IM_STRINGIFY_HELPER(_X) // Preprocessor idiom to stringify e.g. an integer.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IM_FLOOR IM_TRUNC #define IM_FLOOR IM_TRUNC
#endif #endif
@@ -438,7 +437,8 @@ IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, co
IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point. IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p); // return previous UTF-8 code-point.
IMGUI_API const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p); // return previous UTF-8 code-point if 'in_p' is not the end of a valid one.
IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line. IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line.
// Helpers: High-level text functions (DO NOT USE!!! THIS IS A MINIMAL SUBSET OF LARGER UPCOMING CHANGES) // Helpers: High-level text functions (DO NOT USE!!! THIS IS A MINIMAL SUBSET OF LARGER UPCOMING CHANGES)
@@ -1294,6 +1294,12 @@ enum ImGuiWindowRefreshFlags_
// Refresh policy/frequency, Load Balancing etc. // Refresh policy/frequency, Load Balancing etc.
}; };
enum ImGuiWindowBgClickFlags_
{
ImGuiWindowBgClickFlags_None = 0,
ImGuiWindowBgClickFlags_Move = 1 << 0, // Click on bg/void + drag to move window. Cleared by default when using io.ConfigWindowsMoveFromTitleBarOnly.
};
enum ImGuiNextWindowDataFlags_ enum ImGuiNextWindowDataFlags_
{ {
ImGuiNextWindowDataFlags_None = 0, ImGuiNextWindowDataFlags_None = 0,
@@ -2357,6 +2363,15 @@ struct ImGuiContextHook
struct ImGuiContext struct ImGuiContext
{ {
bool Initialized; bool Initialized;
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
int FrameCount;
int FrameCountEnded;
int FrameCountPlatformEnded;
int FrameCountRendered;
double Time;
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
ImGuiIO IO; ImGuiIO IO;
ImGuiPlatformIO PlatformIO; ImGuiPlatformIO PlatformIO;
ImGuiStyle Style; ImGuiStyle Style;
@@ -2371,18 +2386,8 @@ struct ImGuiContext
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked(). float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
ImDrawListSharedData DrawListSharedData; ImDrawListSharedData DrawListSharedData;
double Time;
int FrameCount;
int FrameCountEnded;
int FrameCountPlatformEnded;
int FrameCountRendered;
ImGuiID WithinEndChildID; // Set within EndChild() ImGuiID WithinEndChildID; // Set within EndChild()
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data void* TestEngine; // Test engine user data
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
// Inputs // Inputs
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure. ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure.
@@ -2433,11 +2438,11 @@ struct ImGuiContext
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
bool ActiveIdFromShortcut; bool ActiveIdFromShortcut;
ImS8 ActiveIdMouseButton;
ImGuiID ActiveIdDisabledId; // When clicking a disabled item we set ActiveId=window->MoveId to avoid interference with widget code. Actual item ID is stored here. ImGuiID ActiveIdDisabledId; // When clicking a disabled item we set ActiveId=window->MoveId to avoid interference with widget code. Actual item ID is stored here.
int ActiveIdMouseButton : 8;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
ImGuiWindow* ActiveIdWindow;
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
ImGuiDeactivatedItemData DeactivatedItemData; ImGuiDeactivatedItemData DeactivatedItemData;
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX. ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
@@ -2467,6 +2472,7 @@ struct ImGuiContext
ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
bool DebugShowGroupRects; bool DebugShowGroupRects;
bool GcCompactAll; // Request full GC
// Shared stacks // Shared stacks
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line) ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
@@ -2688,6 +2694,7 @@ struct ImGuiContext
// Capture/Logging // Capture/Logging
bool LogEnabled; // Currently capturing bool LogEnabled; // Currently capturing
bool LogLineFirstItem;
ImGuiLogFlags LogFlags; // Capture flags/type ImGuiLogFlags LogFlags; // Capture flags/type
ImGuiWindow* LogWindow; ImGuiWindow* LogWindow;
ImFileHandle LogFile; // If != NULL log to stdout/ file ImFileHandle LogFile; // If != NULL log to stdout/ file
@@ -2695,7 +2702,6 @@ struct ImGuiContext
const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully! const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully!
const char* LogNextSuffix; const char* LogNextSuffix;
float LogLinePosY; float LogLinePosY;
bool LogLineFirstItem;
int LogDepthRef; int LogDepthRef;
int LogDepthToExpand; int LogDepthToExpand;
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
@@ -2873,13 +2879,14 @@ struct IMGUI_API ImGuiWindow
short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0. short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues. short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused. short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
ImGuiDir AutoPosLastDirection;
ImS8 AutoFitFramesX, AutoFitFramesY; ImS8 AutoFitFramesX, AutoFitFramesY;
bool AutoFitOnlyGrows; bool AutoFitOnlyGrows;
ImGuiDir AutoPosLastDirection;
ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size
ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only
ImS8 DisableInputsFrames; // Disable window interactions for N frames ImS8 DisableInputsFrames; // Disable window interactions for N frames
ImGuiWindowBgClickFlags BgClickFlags : 8; // Configure behavior of click+dragging on window bg/void or over items. Default sets by io.ConfigWindowsMoveFromTitleBarOnly. If you use this please report in #3379.
ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use. ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use.
ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use. ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use.
ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use. ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use.

View File

@@ -619,7 +619,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere)) if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere))
{ {
SetActiveID(id, window); SetActiveID(id, window);
g.ActiveIdMouseButton = mouse_button_clicked; g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
{ {
SetFocusID(id, window); SetFocusID(id, window);
@@ -637,7 +637,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
ClearActiveID(); ClearActiveID();
else else
SetActiveID(id, window); // Hold on ID SetActiveID(id, window); // Hold on ID
g.ActiveIdMouseButton = mouse_button_clicked; g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
{ {
SetFocusID(id, window); SetFocusID(id, window);
@@ -675,32 +675,35 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Keyboard/Gamepad navigation handling // Keyboard/Gamepad navigation handling
// We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse. // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav) if ((item_flags & ImGuiItemFlags_Disabled) == 0)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true;
if (g.NavActivateDownId == id)
{ {
bool nav_activated_by_code = (g.NavActivateId == id); if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
bool nav_activated_by_inputs = (g.NavActivatePressedId == id); if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat)) hovered = true;
if (g.NavActivateDownId == id)
{ {
// Avoid pressing multiple keys from triggering excessive amount of repeat events bool nav_activated_by_code = (g.NavActivateId == id);
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space); bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter); if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat))
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate); {
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration); // Avoid pressing multiple keys from triggering excessive amount of repeat events
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
} const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
if (nav_activated_by_code || nav_activated_by_inputs) const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
{ const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
pressed = true; }
SetActiveID(id, window); if (nav_activated_by_code || nav_activated_by_inputs)
g.ActiveIdSource = g.NavInputSource; {
if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)) // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
SetFocusID(id, window); pressed = true;
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut) SetActiveID(id, window);
g.ActiveIdFromShortcut = true; g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut))
SetFocusID(id, window);
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)
g.ActiveIdFromShortcut = true;
}
} }
} }
@@ -754,7 +757,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
} }
// Activation highlight (this may be a remote activation) // Activation highlight (this may be a remote activation)
if (g.NavHighlightActivatedId == id) if (g.NavHighlightActivatedId == id && (item_flags & ImGuiItemFlags_Disabled) == 0)
hovered = true; hovered = true;
if (out_hovered) *out_hovered = hovered; if (out_hovered) *out_hovered = hovered;
@@ -3926,6 +3929,7 @@ namespace ImStb
#include "imstb_textedit.h" #include "imstb_textedit.h"
} }
// If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{ {
IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
@@ -4157,7 +4161,7 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha
// We support partial insertion (with a mod in stb_textedit.h) // We support partial insertion (with a mod in stb_textedit.h)
const int avail = obj->BufCapacity - 1 - obj->TextLen; const int avail = obj->BufCapacity - 1 - obj->TextLen;
if (!is_resizable && new_text_len > avail) if (!is_resizable && new_text_len > avail)
new_text_len = avail; // 0 new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion.
if (new_text_len == 0) if (new_text_len == 0)
return 0; return 0;
@@ -4316,7 +4320,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
// We support partial insertion (with a mod in stb_textedit.h) // We support partial insertion (with a mod in stb_textedit.h)
const int avail = BufSize - 1 - BufTextLen; const int avail = BufSize - 1 - BufTextLen;
if (!is_resizable && new_text_len > avail) if (!is_resizable && new_text_len > avail)
new_text_len = avail; // 0 new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion.
if (new_text_len == 0) if (new_text_len == 0)
return; return;
@@ -4626,9 +4630,7 @@ static ImVec2 InputTextLineIndexGetPosOffset(ImGuiContext& g, ImGuiInputTextStat
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
// Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator. // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
// - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect. // - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect.
// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h // - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
// (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are
// doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@@ -5155,12 +5157,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
// Filter pasted buffer // Filter pasted buffer
const int clipboard_len = (int)ImStrlen(clipboard); const int clipboard_len = (int)ImStrlen(clipboard);
const char* clipboard_end = clipboard + clipboard_len;
ImVector<char> clipboard_filtered; ImVector<char> clipboard_filtered;
clipboard_filtered.reserve(clipboard_len + 1); clipboard_filtered.reserve(clipboard_len + 1);
for (const char* s = clipboard; *s != 0; ) for (const char* s = clipboard; *s != 0; )
{ {
unsigned int c; unsigned int c;
int in_len = ImTextCharFromUtf8(&c, s, NULL); int in_len = ImTextCharFromUtf8(&c, s, clipboard_end);
s += in_len; s += in_len;
if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true)) if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
continue; continue;

View File

@@ -1,9 +1,21 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types. // This is also an example of how you may wrap your own similar types.
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
// Changelog: // Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// Usage:
// {
// #include "misc/cpp/imgui_stdlib.h"
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
// [...]
// std::string my_string;
// ImGui::InputText("my string", &my_string);
// }
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: // See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness

View File

@@ -1,9 +1,21 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types. // This is also an example of how you may wrap your own similar types.
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
// Changelog: // Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// Usage:
// {
// #include "misc/cpp/imgui_stdlib.h"
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
// [...]
// std::string my_string;
// ImGui::InputText("my string", &my_string);
// }
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: // See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness