Merge branch 'master' into docking

# Conflicts:
#	.github/workflows/build.yml
#	backends/imgui_impl_opengl2.cpp
#	backends/imgui_impl_opengl3.cpp
#	backends/imgui_impl_sdl2.cpp
#	examples/example_apple_metal4/main.mm
#	imgui.cpp
This commit is contained in:
ocornut
2026-07-16 15:56:36 +02:00
13 changed files with 358 additions and 100 deletions

View File

@@ -402,6 +402,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
- likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2026/07/08 (1.92.9) - Drag and Drop: commented out legacy name `ImGuiDragDropFlags_SourceAutoExpirePayload` which obsoleted in 1.90.9 (July 2024). Use `ImGuiDragDropFlags_PayloadAutoExpire`.
- 2026/07/06 (1.92.9) - ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover.
- 2026/06/02 (1.92.9) - TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead.
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
@@ -4326,6 +4327,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false;
AnyIdHasBeenEditedThisFrame = false;
ActiveId = 0;
ActiveIdIsAlive = 0;
ActiveIdTimer = 0.0f;
@@ -4939,6 +4941,7 @@ void ImGui::MarkItemEdited(ImGuiID id)
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
ImGuiContext& g = *GImGui;
//IM_ASSERT(g.LastItemData.ID == id); // Failing cases include: "widgets_inputtext_scrolling", "widgets_inputtext_multiline_status", "widgets_selectable_input" = case of e.g TempInputText() overlayed manually with different ID (#2718)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_EditedInternal;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
return;
@@ -4947,16 +4950,15 @@ void ImGui::MarkItemEdited(ImGuiID id)
if (g.ActiveId == id || g.ActiveId == 0)
{
// FIXME: Can't we fully rely on LastItemData yet?
g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true;
if (g.DeactivatedItemData.ID == id)
g.DeactivatedItemData.HasBeenEditedBefore = true;
g.AnyIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedBefore = true;
}
if (g.DeactivatedItemData.ID == id)
g.DeactivatedItemData.HasBeenEditedBefore = true;
// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.DeactivatedItemData.ID == id || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
}
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
@@ -5864,6 +5866,7 @@ void ImGui::NewFrame()
g.LastActiveIdTimer += g.IO.DeltaTime;
g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdIsAlive = 0;
g.AnyIdHasBeenEditedThisFrame = false;
g.ActiveIdHasBeenEditedThisFrame = false;
g.ActiveIdIsJustActivated = false;
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
@@ -5878,6 +5881,8 @@ void ImGui::NewFrame()
if (g.DeactivatedItemData.ElapseFrame < g.FrameCount)
g.DeactivatedItemData.ID = 0;
g.DeactivatedItemData.IsAlive = false;
if (g.InputTextDeactivatedState.ElapseFrame < g.FrameCount)
g.InputTextDeactivatedState.ID = 0;
// Record when we have been stationary as this state is preserved while over same item.
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
@@ -6619,6 +6624,7 @@ bool ImGui::IsItemDeactivated()
return g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 && g.DeactivatedItemData.ElapseFrame >= g.FrameCount;
}
// Since 1.92.9: consider using NoLiveEdit flags if all you need to that values are not written bo backing variable while typing.
bool ImGui::IsItemDeactivatedAfterEdit()
{
ImGuiContext& g = *GImGui;
@@ -6706,7 +6712,7 @@ bool ImGui::IsItemEdited()
void ImGui::SetNextItemAllowOverlap()
{
ImGuiContext& g = *GImGui;
g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_AllowOverlap;
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -6985,21 +6991,43 @@ ImGuiWindow* ImGui::FindWindowByName(const char* name)
static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
{
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
window->ViewportPos = main_viewport->Pos;
if (settings->ViewportId)
if (settings != NULL)
{
window->ViewportId = settings->ViewportId;
window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
window->ViewportPos = main_viewport->Pos;
if (settings->ViewportId)
{
window->ViewportId = settings->ViewportId;
window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
}
window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
if (settings->Size.x > 0 && settings->Size.y > 0)
{
window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
window->AutoFitFramesX = window->AutoFitFramesY = 0;
}
window->Collapsed = settings->Collapsed;
window->DockId = settings->DockId;
window->DockOrder = settings->DockOrder;
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
}
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values
if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
{
window->AutoFitFramesX = window->AutoFitFramesY = 2;
window->AutoFitOnlyGrows = false;
}
else
{
window->AutoFitFramesX = (window->Size.x <= 0.0f) ? 2 : 0;
window->AutoFitFramesY = (window->Size.y <= 0.0f) ? 2 : 0;
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
}
window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
if (settings->Size.x > 0 && settings->Size.y > 0)
window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
window->Collapsed = settings->Collapsed;
window->DockId = settings->DockId;
window->DockOrder = settings->DockOrder;
}
// Note that 'settings' may be NULL.
// Sets _Once, _Appearing, _FirstUseEver. _FirstUseEver will be cleared again if there are settings.
static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
{
// Initial window state with e.g. default/arbitrary window position
@@ -7010,28 +7038,9 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s
window->Size = window->SizeFull = ImVec2(0, 0);
window->ViewportPos = main_viewport->Pos;
window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
ApplyWindowSettings(window, settings);
if (settings != NULL)
{
settings->LastUsedDate = g.SessionDate;
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
ApplyWindowSettings(window, settings);
}
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values
if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
{
window->AutoFitFramesX = window->AutoFitFramesY = 2;
window->AutoFitOnlyGrows = false;
}
else
{
if (window->Size.x <= 0.0f)
window->AutoFitFramesX = 2;
if (window->Size.y <= 0.0f)
window->AutoFitFramesY = 2;
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
}
}
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
@@ -12116,7 +12125,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
g.LastItemData.ID = id;
g.LastItemData.Rect = bb;
g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlagsSet | extra_flags;
g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
// Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared.
@@ -12150,7 +12159,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// Lightweight clear of SetNextItemXXX data.
g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
g.NextItemData.ItemFlags = ImGuiItemFlags_None;
g.NextItemData.ItemFlagsSet = ImGuiItemFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (id != 0)
@@ -12560,7 +12569,7 @@ void ImGui::BeginGroup()
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupIsSameLine = window->DC.IsSameLine;
group_data.BackupActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame;
group_data.BackupAnyIdHasBeenEditedThisFrame = g.AnyIdHasBeenEditedThisFrame;
group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
group_data.EmitItem = true;
@@ -12625,7 +12634,7 @@ void ImGui::EndGroup()
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
// Forward Edited flag
if (g.ActiveIdHasBeenEditedThisFrame && !group_data.BackupActiveIdHasBeenEditedThisFrame)
if (g.AnyIdHasBeenEditedThisFrame && !group_data.BackupAnyIdHasBeenEditedThisFrame)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
// Forward Deactivated flag
@@ -16531,7 +16540,10 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
// Call post-read handlers
ImGuiSettingsCleanupArgs cleanup_args;
if (g.IO.ConfigIniSettingsAutoDiscardMonths > 0)
{
cleanup_args.DiscardOlderThanMonths = g.IO.ConfigIniSettingsAutoDiscardMonths;
CleanupIniSettings(&cleanup_args);
}
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
if (handler.ApplyAllFn != NULL)
handler.ApplyAllFn(&g, &handler);