|
|
@@ -27,7 +27,7 @@
|
|
|
// Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there.
|
|
|
// Since 1.92, we encourage font loading questions to also be posted in 'Issues'.
|
|
|
|
|
|
-// Copyright (c) 2014-2025 Omar Cornut
|
|
|
+// Copyright (c) 2014-2026 Omar Cornut
|
|
|
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
|
|
|
// See LICENSE.txt for copyright and licensing details (standard MIT License).
|
|
|
// This library is free but needs your support to sustain development and maintenance.
|
|
|
@@ -394,6 +394,25 @@ 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.
|
|
|
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
|
|
|
|
|
+ - 2026/01/08 (1.92.6) - Commented out legacy names obsoleted in 1.90 (Sept 2023): 'BeginChildFrame()' --> 'BeginChild()' with 'ImGuiChildFlags_FrameStyle'. 'EndChildFrame()' --> 'EndChild()'. 'ShowStackToolWindow()' --> 'ShowIDStackToolWindow()'. 'IM_OFFSETOF()' --> 'offsetof()'.
|
|
|
+ - 2026/01/07 (1.92.6) - Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). Default value has same meaning before and after.
|
|
|
+ - Refer to GitHub topic #9157 if you have any question.
|
|
|
+ - Before this version, those functions had a 'ImGuiPopupFlags popup_flags = 1' default value in their function signature.
|
|
|
+ Explicitly passing a literal 0 meant ImGuiPopupFlags_MouseButtonLeft. The default literal 1 meant ImGuiPopupFlags_MouseButtonRight.
|
|
|
+ This was introduced by a change on 2020/06/23 (1.77) while changing the signature from 'int mouse_button' to 'ImGuiPopupFlags popup_flags' and trying to preserve then-legacy behavior.
|
|
|
+ We have now changed this behavior to cleanup a very old API quirk, facilitate use by bindings, and to remove the last and error-prone non-zero default value.
|
|
|
+ Also because we deemed it extremely rare to use those helper functions with the Left mouse button! As using the LMB would generally be triggered via another widget, e.g. a Button() + a OpenPopup()/BeginPopup() call.
|
|
|
+ - Before: The default = 1 means ImGuiPopupFlags_MouseButtonRight. Explicitly passing a literal 0 means ImGuiPopupFlags_MouseButtonLeft.
|
|
|
+ - After: The default = 0 means ImGuiPopupFlags_MouseButtonRight. Explicitly passing a literal 1 also means ImGuiPopupFlags_MouseButtonRight (if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
|
|
|
+ - TL;DR: if you don't want to use right mouse button for popups, always specify it explicitly using a named ImGuiPopupFlags_MouseButtonXXXX value.
|
|
|
+ Recap:
|
|
|
+ - BeginPopupContextItem("foo"); // Behavior unchanged (use Right button)
|
|
|
+ - BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft); // Behavior unchanged (use Left button)
|
|
|
+ - BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft | xxx); // Behavior unchanged (use Left button + flags)
|
|
|
+ - BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonRight | xxx); // Behavior unchanged (use Right button + flags)
|
|
|
+ - BeginPopupContextItem("foo", 1); // Behavior unchanged (as a courtesy we legacy interpret 1 as ImGuiPopupFlags_MouseButtonRight, will assert if disabling legacy behaviors.
|
|
|
+ - BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
|
|
|
+ - BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
|
|
|
- 2025/12/23 (1.92.6) - Fonts:AddFontDefault() now automatically selects an embedded font between the new scalable AddFontDefaultVector() and the classic pixel-clean AddFontDefaultBitmap().
|
|
|
The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi) reaching a small threshold. Prefer calling either based on your own logic. You can call AddFontDefaultBitmap() to ensure legacy behavior.
|
|
|
- 2025/12/23 (1.92.6) - Fonts: removed ImFontConfig::PixelSnapV added in 1.92 which turns out is unnecessary (and misdocumented). Post-rescale GlyphOffset is always rounded.
|
|
|
@@ -1262,6 +1281,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|
|
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
|
|
|
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
|
|
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
|
|
|
+#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
|
|
#endif
|
|
|
|
|
|
// Debug options
|
|
|
@@ -1331,8 +1351,8 @@ static bool NavScoreItem(ImGuiNavItemData* result, const ImRect& nav
|
|
|
static void NavApplyItemToResult(ImGuiNavItemData* result);
|
|
|
static void NavProcessItem();
|
|
|
static void NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
|
|
|
-static ImGuiInputSource NavCalcPreferredRefPosSource();
|
|
|
-static ImVec2 NavCalcPreferredRefPos();
|
|
|
+static ImGuiInputSource NavCalcPreferredRefPosSource(ImGuiWindowFlags window_type);
|
|
|
+static ImVec2 NavCalcPreferredRefPos(ImGuiWindowFlags window_type);
|
|
|
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
|
|
|
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
|
|
|
static void NavRestoreLayer(ImGuiNavLayer layer);
|
|
|
@@ -1453,6 +1473,7 @@ ImGuiStyle::ImGuiStyle()
|
|
|
GrabMinSize = 12.0f; // Minimum width/height of a grab box for slider/scrollbar
|
|
|
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
|
|
LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
|
|
|
+ ImageRounding = 0.0f; // Rounding of Image() calls.
|
|
|
ImageBorderSize = 0.0f; // Thickness of border around tabs.
|
|
|
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
|
|
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
|
|
@@ -1527,6 +1548,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
|
|
GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
|
|
|
GrabRounding = ImTrunc(GrabRounding * scale_factor);
|
|
|
LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
|
|
|
+ ImageRounding = ImTrunc(ImageRounding * scale_factor);
|
|
|
ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
|
|
|
TabRounding = ImTrunc(TabRounding * scale_factor);
|
|
|
TabMinWidthBase = ImTrunc(TabMinWidthBase * scale_factor);
|
|
|
@@ -3586,6 +3608,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ScrollbarPadding) }, // ImGuiStyleVar_ScrollbarPadding
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
|
|
|
+ { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ImageRounding) }, // ImGuiStyleVar_ImageRounding
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ImageBorderSize) }, // ImGuiStyleVar_ImageBorderSize
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
|
|
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize
|
|
|
@@ -3615,11 +3638,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
- if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 1)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(var_info->DataType == ImGuiDataType_Float && var_info->Count == 1, "Calling PushStyleVar() variant with wrong type!");
|
|
|
float* pvar = (float*)var_info->GetVarPtr(&g.Style);
|
|
|
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
|
|
|
*pvar = val;
|
|
|
@@ -3629,11 +3648,7 @@ void ImGui::PushStyleVarX(ImGuiStyleVar idx, float val_x)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
- if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(var_info->DataType == ImGuiDataType_Float && var_info->Count == 2, "Calling PushStyleVar() variant with wrong type!");
|
|
|
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
|
|
|
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
|
|
|
pvar->x = val_x;
|
|
|
@@ -3643,11 +3658,7 @@ void ImGui::PushStyleVarY(ImGuiStyleVar idx, float val_y)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
- if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(var_info->DataType == ImGuiDataType_Float && var_info->Count == 2, "Calling PushStyleVar() variant with wrong type!");
|
|
|
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
|
|
|
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
|
|
|
pvar->y = val_y;
|
|
|
@@ -3657,11 +3668,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
- if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(var_info->DataType == ImGuiDataType_Float && var_info->Count == 2, "Calling PushStyleVar() variant with wrong type!");
|
|
|
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
|
|
|
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
|
|
|
*pvar = val;
|
|
|
@@ -4808,7 +4815,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
|
|
// Test if another item is active (e.g. being dragged)
|
|
|
const ImGuiID id = g.LastItemData.ID;
|
|
|
if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
|
|
|
- if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
|
|
|
+ if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap && !g.ActiveIdFromShortcut)
|
|
|
{
|
|
|
// When ActiveId == MoveId it means that either:
|
|
|
// - (1) user clicked on void _or_ an item with no id, which triggers moving window (ActiveId is set even when window has _NoMove flag)
|
|
|
@@ -5071,10 +5078,11 @@ void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// A conformant backend should return NULL on failure (e.g. clipboard data is not text).
|
|
|
const char* ImGui::GetClipboardText()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- return g.PlatformIO.Platform_GetClipboardTextFn ? g.PlatformIO.Platform_GetClipboardTextFn(&g) : "";
|
|
|
+ return g.PlatformIO.Platform_GetClipboardTextFn ? g.PlatformIO.Platform_GetClipboardTextFn(&g) : NULL;
|
|
|
}
|
|
|
|
|
|
void ImGui::SetClipboardText(const char* text)
|
|
|
@@ -5920,11 +5928,7 @@ void ImGui::EndFrame()
|
|
|
// Don't process EndFrame() multiple times.
|
|
|
if (g.FrameCountEnded == g.FrameCount)
|
|
|
return;
|
|
|
- if (!g.WithinFrameScope)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(g.WithinFrameScope, "Forgot to call ImGui::NewFrame()?");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(g.WithinFrameScope, "Forgot to call ImGui::NewFrame()?");
|
|
|
|
|
|
CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
|
|
|
|
|
|
@@ -6370,10 +6374,8 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
|
|
IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 && "Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
|
|
|
}
|
|
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
|
|
- //if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
|
|
|
- // child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
|
|
|
- //if (window_flags & ImGuiWindowFlags_NavFlattened)
|
|
|
- // child_flags |= ImGuiChildFlags_NavFlattened;
|
|
|
+ //if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding) { child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding; }
|
|
|
+ //if (window_flags & ImGuiWindowFlags_NavFlattened) { child_flags |= ImGuiChildFlags_NavFlattened; }
|
|
|
#endif
|
|
|
if (child_flags & ImGuiChildFlags_AutoResizeX)
|
|
|
child_flags &= ~ImGuiChildFlags_ResizeX;
|
|
|
@@ -7006,7 +7008,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, int* border_hove
|
|
|
if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
|
|
|
{
|
|
|
const float NAV_RESIZE_SPEED = 600.0f;
|
|
|
- const float resize_step = NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y);
|
|
|
+ const float resize_step = NAV_RESIZE_SPEED * g.IO.DeltaTime * GetScale();
|
|
|
g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
|
|
|
g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size); // We need Pos+Size >= clmap_rect.Min, so Size >= clmap_rect.Min - Pos, so size_delta >= clmap_rect.Min - window->Pos - window->Size
|
|
|
g.NavWindowingToggleLayer = false;
|
|
|
@@ -7129,7 +7131,13 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
|
|
}
|
|
|
if (override_alpha)
|
|
|
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
|
|
|
- window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
|
|
|
+ if (bg_col & IM_COL32_A_MASK)
|
|
|
+ {
|
|
|
+ ImRect bg_rect(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size);
|
|
|
+ ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom;
|
|
|
+ ImDrawList* bg_draw_list = window->DrawList;
|
|
|
+ bg_draw_list->AddRectFilled(bg_rect.Min, bg_rect.Max, bg_col, window_rounding, bg_rounding_flags);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Title bar
|
|
|
@@ -7976,13 +7984,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
|
|
|
|
|
|
// Default item width. Make it proportional to window size if window manually resizes
|
|
|
- if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
|
|
|
- window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
|
|
|
+ const bool is_resizable_window = (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize));
|
|
|
+ if (is_resizable_window)
|
|
|
+ window->DC.ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
|
|
|
else
|
|
|
- window->ItemWidthDefault = ImTrunc(g.FontSize * 16.0f);
|
|
|
- window->DC.ItemWidth = window->ItemWidthDefault;
|
|
|
- window->DC.TextWrapPos = -1.0f; // disabled
|
|
|
+ window->DC.ItemWidthDefault = ImTrunc(g.FontSize * 16.0f);
|
|
|
+ window->DC.ItemWidth = window->DC.ItemWidthDefault;
|
|
|
window->DC.ItemWidthStack.resize(0);
|
|
|
+ window->DC.TextWrapPos = -1.0f; // Disabled
|
|
|
window->DC.TextWrapPosStack.resize(0);
|
|
|
if (flags & ImGuiWindowFlags_Modal)
|
|
|
window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg));
|
|
|
@@ -8202,11 +8211,7 @@ void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
|
|
|
void ImGui::PopItemFlag()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (g.ItemFlagsStack.Size <= 1)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PopItemFlag() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(g.ItemFlagsStack.Size > 1, "Calling PopItemFlag() too many times!");
|
|
|
g.ItemFlagsStack.pop_back();
|
|
|
g.CurrentItemFlags = g.ItemFlagsStack.back();
|
|
|
}
|
|
|
@@ -8236,11 +8241,7 @@ void ImGui::BeginDisabled(bool disabled)
|
|
|
void ImGui::EndDisabled()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (g.DisabledStackSize <= 0)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling EndDisabled() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(g.DisabledStackSize > 0, "Calling EndDisabled() too many times!");
|
|
|
g.DisabledStackSize--;
|
|
|
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
|
|
|
//PopItemFlag();
|
|
|
@@ -8267,8 +8268,8 @@ void ImGui::BeginDisabledOverrideReenable()
|
|
|
void ImGui::EndDisabledOverrideReenable()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- g.DisabledStackSize--;
|
|
|
IM_ASSERT(g.DisabledStackSize > 0);
|
|
|
+ g.DisabledStackSize--;
|
|
|
g.ItemFlagsStack.pop_back();
|
|
|
g.CurrentItemFlags = g.ItemFlagsStack.back();
|
|
|
g.Style.Alpha = g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup;
|
|
|
@@ -8287,11 +8288,7 @@ void ImGui::PopTextWrapPos()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
- if (window->DC.TextWrapPosStack.Size <= 0)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(window->DC.TextWrapPosStack.Size > 0, "Calling PopTextWrapPos() too many times!");
|
|
|
window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
|
|
|
window->DC.TextWrapPosStack.pop_back();
|
|
|
}
|
|
|
@@ -8690,11 +8687,7 @@ void ImGui::PushFocusScope(ImGuiID id)
|
|
|
void ImGui::PopFocusScope()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (g.FocusScopeStack.Size <= g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PopFocusScope() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(g.FocusScopeStack.Size > g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack, "Calling PopFocusScope() too many times!");
|
|
|
g.FocusScopeStack.pop_back();
|
|
|
g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0;
|
|
|
}
|
|
|
@@ -9027,7 +9020,7 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
|
|
|
|
|
|
// Global scale factors
|
|
|
final_size *= g.Style.FontScaleMain; // Main global scale factor
|
|
|
- final_size *= g.Style.FontScaleDpi; // Per-monitor/viewport DPI scale factor, automatically updated when io.ConfigDpiScaleFonts is enabled.
|
|
|
+ final_size *= g.Style.FontScaleDpi; // Per-monitor/viewport DPI scale factor (in docking branch: automatically updated when io.ConfigDpiScaleFonts is enabled).
|
|
|
|
|
|
// Window scale (mostly obsolete now)
|
|
|
if (window != NULL)
|
|
|
@@ -9085,11 +9078,7 @@ void ImGui::PushFont(ImFont* font, float font_size_base)
|
|
|
void ImGui::PopFont()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (g.FontStack.Size <= 0)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(g.FontStack.Size > 0, "Calling PopFont() too many times!");
|
|
|
ImFontStackData* font_stack_data = &g.FontStack.back();
|
|
|
SetCurrentFont(font_stack_data->Font, font_stack_data->FontSizeBeforeScaling, font_stack_data->FontSizeAfterScaling);
|
|
|
g.FontStack.pop_back();
|
|
|
@@ -9229,11 +9218,7 @@ ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed)
|
|
|
void ImGui::PopID()
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
- if (window->IDStack.Size <= 1)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling PopID() too many times!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET(window->IDStack.Size > 1, "Calling PopID() too many times!");
|
|
|
window->IDStack.pop_back();
|
|
|
}
|
|
|
|
|
|
@@ -10507,6 +10492,8 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
|
|
#endif
|
|
|
|
|
|
// Remaining events will be processed on the next frame
|
|
|
+ // FIXME-MULTITHREADING: io.AddKeyEvent() etc. calls are mostly thread-safe apart from the fact they push to this
|
|
|
+ // queue which may be resized here. Could potentially rework this to narrow down the section needing a mutex? (#5772)
|
|
|
if (event_n == g.InputEventsQueue.Size)
|
|
|
g.InputEventsQueue.resize(0);
|
|
|
else
|
|
|
@@ -11473,7 +11460,7 @@ void ImGui::PushItemWidth(float item_width)
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width
|
|
|
- window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
|
|
|
+ window->DC.ItemWidth = (item_width == 0.0f ? window->DC.ItemWidthDefault : item_width);
|
|
|
g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
|
|
|
}
|
|
|
|
|
|
@@ -12187,7 +12174,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
|
|
|
popup_ref.RestoreNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type).
|
|
|
popup_ref.OpenFrameCount = g.FrameCount;
|
|
|
popup_ref.OpenParentId = parent_window->IDStack.back();
|
|
|
- popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
|
|
|
+ popup_ref.OpenPopupPos = NavCalcPreferredRefPos(ImGuiWindowFlags_Popup);
|
|
|
popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
|
|
|
|
|
|
IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopupEx(0x%08X)\n", id);
|
|
|
@@ -12438,11 +12425,7 @@ void ImGui::EndPopup()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
- if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || g.BeginPopupStack.Size == 0)
|
|
|
- {
|
|
|
- IM_ASSERT_USER_ERROR(0, "Calling EndPopup() too many times or in wrong window!");
|
|
|
- return;
|
|
|
- }
|
|
|
+ IM_ASSERT_USER_ERROR_RET((window->Flags & ImGuiWindowFlags_Popup) != 0 && g.BeginPopupStack.Size > 0, "Calling EndPopup() in wrong window!");
|
|
|
|
|
|
// Make all menus and popups wrap around for now, may need to expose that policy (e.g. focus scope could include wrap/loop policy flags used by new move requests)
|
|
|
if (g.NavWindow == window)
|
|
|
@@ -12456,13 +12439,26 @@ void ImGui::EndPopup()
|
|
|
g.WithinEndChildID = backup_within_end_child_id;
|
|
|
}
|
|
|
|
|
|
+ImGuiMouseButton ImGui::GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags)
|
|
|
+{
|
|
|
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
|
|
+ if ((flags & ImGuiPopupFlags_InvalidMask_) != 0) // 1,2 --> ImGuiMouseButton_Right, ImGuiMouseButton_Middle
|
|
|
+ return (flags & ImGuiPopupFlags_InvalidMask_);
|
|
|
+#else
|
|
|
+ IM_ASSERT((flags & ImGuiPopupFlags_InvalidMask_) == 0);
|
|
|
+#endif
|
|
|
+ if (flags & ImGuiPopupFlags_MouseButtonMask_)
|
|
|
+ return ((flags & ImGuiPopupFlags_MouseButtonMask_) >> ImGuiPopupFlags_MouseButtonShift_) - 1;
|
|
|
+ return ImGuiMouseButton_Right; // Default == 1
|
|
|
+}
|
|
|
+
|
|
|
// 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()
|
|
|
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
- int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
|
|
|
+ ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
|
|
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!
|
|
|
@@ -12495,7 +12491,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag
|
|
|
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!
|
|
|
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
|
|
|
- int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
|
|
|
+ ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
|
|
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
|
OpenPopupEx(id, popup_flags);
|
|
|
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
|
|
@@ -12508,7 +12504,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl
|
|
|
if (!str_id)
|
|
|
str_id = "window_context";
|
|
|
ImGuiID id = window->GetID(str_id);
|
|
|
- int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
|
|
|
+ ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
|
|
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
|
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
|
|
|
OpenPopupEx(id, popup_flags);
|
|
|
@@ -12522,7 +12518,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flag
|
|
|
if (!str_id)
|
|
|
str_id = "void_context";
|
|
|
ImGuiID id = window->GetID(str_id);
|
|
|
- int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
|
|
|
+ ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
|
|
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
|
|
|
if (GetTopMostPopupModal() == NULL)
|
|
|
OpenPopupEx(id, popup_flags);
|
|
|
@@ -12652,9 +12648,9 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
|
|
// as drag and drop tooltips are calling SetNextWindowPos() leading to 'window_pos_set_by_api' being set in Begin().
|
|
|
IM_ASSERT(g.CurrentWindow == window);
|
|
|
const float scale = g.Style.MouseCursorScale;
|
|
|
- const ImVec2 ref_pos = NavCalcPreferredRefPos();
|
|
|
+ const ImVec2 ref_pos = NavCalcPreferredRefPos(ImGuiWindowFlags_Tooltip);
|
|
|
|
|
|
- if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource() == ImGuiInputSource_Mouse)
|
|
|
+ if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource(ImGuiWindowFlags_Tooltip) == ImGuiInputSource_Mouse)
|
|
|
{
|
|
|
ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
|
|
|
if (r_outer.Contains(ImRect(tooltip_pos, tooltip_pos + window->Size)))
|
|
|
@@ -12793,6 +12789,7 @@ void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
|
|
|
}
|
|
|
|
|
|
// Note technically focus related but rather adjacent and close to BringWindowToFocusFront()
|
|
|
+// FIXME-FOCUS: Could opt-in/opt-out enable modal check like in FocusWindow().
|
|
|
void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -13026,6 +13023,8 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
|
|
window->NavLastIds[nav_layer] = id;
|
|
|
if (g.LastItemData.ID == id)
|
|
|
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
|
|
+ if (id == g.ActiveIdIsAlive)
|
|
|
+ g.NavIdIsAlive = true;
|
|
|
|
|
|
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
|
|
g.NavHighlightItemUnderNav = true;
|
|
|
@@ -13450,7 +13449,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wra
|
|
|
|
|
|
// In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it:
|
|
|
// as NavEndFrame() will do the same test. It will end up calling NavUpdateCreateWrappingRequest().
|
|
|
- if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main)
|
|
|
+ if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == window->DC.NavLayerCurrent)
|
|
|
g.NavMoveFlags = (g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
|
|
|
}
|
|
|
|
|
|
@@ -13537,31 +13536,29 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
|
|
|
+// Positioning logic altered slightly for remote activation: for Popup we want to use item rect, for Tooltip we leave things alone. (#9138)
|
|
|
+// When calling for ImGuiWindowFlags_Popup we use LastItemData.
|
|
|
+static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource(ImGuiWindowFlags window_type)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
+
|
|
|
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
|
|
|
+ if ((window_type & ImGuiWindowFlags_Popup) && activated_shortcut)
|
|
|
+ return ImGuiInputSource_Keyboard;
|
|
|
|
|
|
- // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
|
|
|
- if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
|
|
|
+ if (!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window)
|
|
|
return ImGuiInputSource_Mouse;
|
|
|
else
|
|
|
return ImGuiInputSource_Keyboard; // or Nav in general
|
|
|
}
|
|
|
|
|
|
-static ImVec2 ImGui::NavCalcPreferredRefPos()
|
|
|
+static ImVec2 ImGui::NavCalcPreferredRefPos(ImGuiWindowFlags window_type)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
- ImGuiInputSource source = NavCalcPreferredRefPosSource();
|
|
|
-
|
|
|
- const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
|
|
|
+ ImGuiInputSource source = NavCalcPreferredRefPosSource(window_type);
|
|
|
|
|
|
- if (source != ImGuiInputSource_Mouse && !activated_shortcut && window == NULL)
|
|
|
- source = ImGuiInputSource_Mouse;
|
|
|
-
|
|
|
- // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
|
|
|
if (source == ImGuiInputSource_Mouse)
|
|
|
{
|
|
|
// Mouse (we need a fallback in case the mouse becomes invalid after being used)
|
|
|
@@ -13573,8 +13570,9 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
|
|
|
else
|
|
|
{
|
|
|
// When navigation is active and mouse is disabled, pick a position around the bottom left of the currently navigated item
|
|
|
+ const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
|
|
|
ImRect ref_rect;
|
|
|
- if (activated_shortcut)
|
|
|
+ if (activated_shortcut && (window_type & ImGuiWindowFlags_Popup))
|
|
|
ref_rect = g.LastItemData.NavRect;
|
|
|
else if (window != NULL)
|
|
|
ref_rect = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]);
|
|
|
@@ -13773,7 +13771,7 @@ static void ImGui::NavUpdate()
|
|
|
// Update mouse position if requested
|
|
|
// (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied)
|
|
|
if (set_mouse_pos && io.ConfigNavMoveSetMousePos && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
|
|
|
- TeleportMousePos(NavCalcPreferredRefPos());
|
|
|
+ TeleportMousePos(NavCalcPreferredRefPos(ImGuiWindowFlags_Popup));
|
|
|
|
|
|
// [DEBUG]
|
|
|
g.NavScoringDebugCount = 0;
|
|
|
@@ -14266,9 +14264,13 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|
|
|
|
|
const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
|
|
|
//const ImGuiAxis move_axis = (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
|
|
|
+
|
|
|
+ // Menu layer does not maintain scrolling / content size (#9178)
|
|
|
+ ImVec2 wrap_size = (g.NavLayer == ImGuiNavLayer_Menu) ? window->Size : window->ContentSize + window->WindowPadding;
|
|
|
+
|
|
|
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
|
|
{
|
|
|
- bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
|
|
|
+ bb_rel.Min.x = bb_rel.Max.x = wrap_size.x;
|
|
|
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
|
|
{
|
|
|
bb_rel.TranslateY(-bb_rel.GetHeight()); // Previous row
|
|
|
@@ -14288,7 +14290,7 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|
|
}
|
|
|
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
|
|
{
|
|
|
- bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
|
|
|
+ bb_rel.Min.y = bb_rel.Max.y = wrap_size.y;
|
|
|
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
|
|
{
|
|
|
bb_rel.TranslateX(-bb_rel.GetWidth()); // Previous column
|
|
|
@@ -14528,7 +14530,7 @@ static void ImGui::NavUpdateWindowing()
|
|
|
if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
|
|
|
{
|
|
|
const float NAV_MOVE_SPEED = 800.0f;
|
|
|
- const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
|
|
+ const float move_step = NAV_MOVE_SPEED * io.DeltaTime * GetScale();
|
|
|
g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
|
|
|
g.NavHighlightItemUnderNav = true;
|
|
|
ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos);
|
|
|
@@ -15078,7 +15080,7 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
|
|
|
if (!text_end)
|
|
|
text_end = FindRenderedTextEnd(text, text_end);
|
|
|
|
|
|
- const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + g.Style.FramePadding.y + 1);
|
|
|
+ const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + ImMax(g.Style.FramePadding.y, g.Style.ItemSpacing.y) + 1);
|
|
|
if (ref_pos)
|
|
|
g.LogLinePosY = ref_pos->y;
|
|
|
if (log_new_line)
|