Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Taudul <wolf@nereid.pl>2021-03-15 23:13:01 +0300
committerBartosz Taudul <wolf@nereid.pl>2021-03-15 23:13:01 +0300
commit06b1214affc0c8099e885385fbb6b8424ad49bec (patch)
treeec9603c2636774ae9565419f7b3e2a52146783c2 /imgui/imgui.cpp
parent753c007557989615b3bb02058ddf835299a7abe8 (diff)
Update ImGUI to 1.82 + docking.
Diffstat (limited to 'imgui/imgui.cpp')
-rw-r--r--imgui/imgui.cpp663
1 files changed, 378 insertions, 285 deletions
diff --git a/imgui/imgui.cpp b/imgui/imgui.cpp
index 1d5c88a1..1bf605ad 100644
--- a/imgui/imgui.cpp
+++ b/imgui/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.81
+// dear imgui, v1.82
// (main code and documentation)
// Help:
@@ -15,6 +15,7 @@
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Wiki https://github.com/ocornut/imgui/wiki
// - Issues & support https://github.com/ocornut/imgui/issues
+// - Discussions https://github.com/ocornut/imgui/discussions
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
// See LICENSE.txt for copyright and licensing details (standard MIT License).
@@ -376,15 +377,34 @@ CODE
When you are not sure about a 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.
- (Docking/Viewport Branch)
- - 2020/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
+(Docking/Viewport Branch)
+ - 2021/XX/XX (1.XX) - when multi-viewports are enabled, all positions will be in your natural OS coordinates space. It means that:
- reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are probably not what you want anymore.
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.
- - 2020/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
-
-
+ - 2021/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
+
+
+ - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
+ - ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft
+ - ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight
+ - ImDrawCornerFlags_None -> use ImDrawFlags_RoundCornersNone etc.
+ flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API.
+ breaking: the default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners":
+ - rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use)
+ - rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use)
+ - rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use)
+ - rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use): will now round all corners --> use ImDrawFlags_RoundCornersNone or rounding == 0.0f.
+ this ONLY matters for hard coded use of 0 + rounding > 0.0f. Use of named ImDrawFlags_RoundCornersNone (new) or ImDrawCornerFlags_None (old) are ok.
+ the old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners" and we sometimes encouraged using them as shortcuts.
+ legacy path still support use of hard coded ~0 or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise).
+ - 2021/03/11 (1.82) - removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
+ - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY()
+ - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing.
+ - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
+ - 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'.
+ - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed.
- 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete).
- removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).
- renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete).
@@ -896,6 +916,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb
static ImVec2 NavCalcPreferredRefPos();
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
+static void NavRestoreLayer(ImGuiNavLayer layer);
static int FindWindowFocusIndex(ImGuiWindow* window);
// Error Checking
@@ -934,27 +955,33 @@ static void UpdateViewportPlatformMonitor(ImGuiViewportP* viewport);
// [SECTION] CONTEXT AND MEMORY ALLOCATORS
//-----------------------------------------------------------------------------
+// DLL users:
+// - Heaps and globals are not shared across DLL boundaries!
+// - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from.
+// - Same apply for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanism works without DLL).
+// - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in).
+
// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
-// ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
-// 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call
-// SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading.
-// In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into.
-// 2) Important: Dear ImGui functions are not thread-safe because of this pointer.
-// If you want thread-safety to allow N threads to access N different contexts, you can:
-// - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h:
-// struct ImGuiContext;
-// extern thread_local ImGuiContext* MyImGuiTLS;
-// #define GImGui MyImGuiTLS
-// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
-// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
-// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
+// - ImGui::CreateContext() will automatically set this pointer if it is NULL.
+// Change to a different context by calling ImGui::SetCurrentContext().
+// - Important: Dear ImGui functions are not thread-safe because of this pointer.
+// If you want thread-safety to allow N threads to access N different contexts:
+// - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h:
+// struct ImGuiContext;
+// extern thread_local ImGuiContext* MyImGuiTLS;
+// #define GImGui MyImGuiTLS
+// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
+// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
+// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
+// - DLL users: read comments above.
#ifndef GImGui
ImGuiContext* GImGui = NULL;
#endif
// Memory Allocator functions. Use SetAllocatorFunctions() to change them.
-// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
-// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+// - You probably don't want to modify those mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+// - DLL users: read comments above.
#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); }
@@ -962,10 +989,9 @@ static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_d
static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
#endif
-
-static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
-static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
-static void* GImAllocatorUserData = NULL;
+static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
+static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
+static void* GImAllocatorUserData = NULL;
//-----------------------------------------------------------------------------
// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
@@ -1011,7 +1037,7 @@ ImGuiStyle::ImGuiStyle()
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering.
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
- CircleSegmentMaxError = 1.60f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
+ CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
// Default theme
ImGui::StyleColorsDark(this);
@@ -2842,8 +2868,8 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
const float border_size = g.Style.FrameBorderSize;
if (border && border_size > 0.0f)
{
- window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
- window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
}
}
@@ -2854,8 +2880,8 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
const float border_size = g.Style.FrameBorderSize;
if (border_size > 0.0f)
{
- window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
- window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
}
}
@@ -2881,13 +2907,13 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
bool fully_visible = window->ClipRect.Contains(display_rect);
if (!fully_visible)
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
- window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
+ window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, 0, THICKNESS);
if (!fully_visible)
window->DrawList->PopClipRect();
}
if (flags & ImGuiNavHighlightFlags_TypeThin)
{
- window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
+ window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, 1.0f);
}
}
@@ -3062,6 +3088,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdTimer = 0.0f;
g.ActiveIdHasBeenPressedBefore = false;
g.ActiveIdHasBeenEditedBefore = false;
+ g.ActiveIdMouseButton = -1;
if (id != 0)
{
g.LastActiveId = id;
@@ -3136,8 +3163,8 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla
// FIXME-OPT: This could be cached/stored within the window.
ImGuiContext& g = *GImGui;
if (g.NavWindow)
- if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
- if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
+ if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindowDockTree)
+ if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
{
// For the purpose of those flags we differentiate "standard popup" from "modal popup"
// NB: The order of those two tests is important because Modal windows are also Popups.
@@ -3149,7 +3176,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla
// Filter by viewport
if (window->Viewport != g.MouseViewport)
- if (g.MovingWindow == NULL || window->RootWindow != g.MovingWindow->RootWindow)
+ if (g.MovingWindow == NULL || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree)
return false;
return true;
@@ -3166,20 +3193,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return IsItemFocused();
// Test for bounding box overlap, as updated as ItemAdd()
- if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
+ ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags;
+ if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
return false;
IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
// Test if we are hovering the right window (our window could be behind another window)
- // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
- // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
- //if (g.HoveredWindow != window)
- // return false;
- if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
- return false;
+ // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
+ // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable
+ // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was
+ // the test that has been running for a long while.
+ if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
+ if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0)
+ return false;
// Test if another item is active (e.g. being dragged)
- if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
return false;
@@ -3274,18 +3303,18 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
// (Note that we can always TAB out of a widget that doesn't allow tabbing in)
- if (g.ActiveId == id && g.FocusTabPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.FocusRequestNextWindow == NULL)
+ if (g.ActiveId == id && g.TabFocusPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.TabFocusRequestNextWindow == NULL)
{
- g.FocusRequestNextWindow = window;
- g.FocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
+ g.TabFocusRequestNextWindow = window;
+ g.TabFocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
}
// Handle focus requests
- if (g.FocusRequestCurrWindow == window)
+ if (g.TabFocusRequestCurrWindow == window)
{
- if (window->DC.FocusCounterRegular == g.FocusRequestCurrCounterRegular)
+ if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
return true;
- if (is_tab_stop && window->DC.FocusCounterTabStop == g.FocusRequestCurrCounterTabStop)
+ if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{
g.NavJustTabbedId = id;
return true;
@@ -3334,7 +3363,7 @@ void* ImGui::MemAlloc(size_t size)
{
if (ImGuiContext* ctx = GImGui)
ctx->IO.MetricsActiveAllocations++;
- return GImAllocatorAllocFunc(size, GImAllocatorUserData);
+ return (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
}
// IM_FREE() == ImGui::MemFree()
@@ -3343,7 +3372,7 @@ void ImGui::MemFree(void* ptr)
if (ptr)
if (ImGuiContext* ctx = GImGui)
ctx->IO.MetricsActiveAllocations--;
- return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
+ return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
}
const char* ImGui::GetClipboardText()
@@ -3380,13 +3409,21 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx)
#endif
}
-void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
+void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data)
{
GImAllocatorAllocFunc = alloc_func;
GImAllocatorFreeFunc = free_func;
GImAllocatorUserData = user_data;
}
+// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
+void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data)
+{
+ *p_alloc_func = GImAllocatorAllocFunc;
+ *p_free_func = GImAllocatorFreeFunc;
+ *p_user_data = GImAllocatorUserData;
+}
+
ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
{
ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
@@ -3527,10 +3564,10 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
SetActiveID(window->MoveId, window);
g.NavDisableHighlight = true;
g.ActiveIdNoClearOnFocusLoss = true;
- g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
+ g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
bool can_move_window = true;
- if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
+ if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
can_move_window = false;
if (ImGuiDockNode* node = window->DockNodeAsHost)
if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
@@ -3578,8 +3615,8 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
// We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
// We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
KeepAliveID(g.ActiveId);
- IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
- ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
+ IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindowDockTree);
+ ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
{
ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
@@ -3643,7 +3680,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
{
// 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.
- ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindowDockStop : NULL;
+ ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
if (root_window != NULL && !is_closed_popup)
@@ -3809,7 +3846,7 @@ void ImGui::UpdateMouseWheel()
const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
const float scale = new_font_scale / window->FontWindowScale;
window->FontWindowScale = new_font_scale;
- if (!(window->Flags & ImGuiWindowFlags_ChildWindow))
+ if (window == window->RootWindow)
{
const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
SetWindowPos(window, window->Pos + offset, 0);
@@ -3858,32 +3895,32 @@ void ImGui::UpdateTabFocus()
ImGuiContext& g = *GImGui;
// Pressing TAB activate widget focus
- g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
- if (g.ActiveId == 0 && g.FocusTabPressed)
+ g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
+ if (g.ActiveId == 0 && g.TabFocusPressed)
{
// Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
- g.FocusRequestNextWindow = g.NavWindow;
- g.FocusRequestNextCounterRegular = INT_MAX;
+ g.TabFocusRequestNextWindow = g.NavWindow;
+ g.TabFocusRequestNextCounterRegular = INT_MAX;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
- g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
+ g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
else
- g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
+ g.TabFocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
}
// Turn queued focus request into current one
- g.FocusRequestCurrWindow = NULL;
- g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX;
- if (g.FocusRequestNextWindow != NULL)
+ g.TabFocusRequestCurrWindow = NULL;
+ g.TabFocusRequestCurrCounterRegular = g.TabFocusRequestCurrCounterTabStop = INT_MAX;
+ if (g.TabFocusRequestNextWindow != NULL)
{
- ImGuiWindow* window = g.FocusRequestNextWindow;
- g.FocusRequestCurrWindow = window;
- if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
- g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
- if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
- g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
- g.FocusRequestNextWindow = NULL;
- g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX;
+ ImGuiWindow* window = g.TabFocusRequestNextWindow;
+ g.TabFocusRequestCurrWindow = window;
+ if (g.TabFocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
+ g.TabFocusRequestCurrCounterRegular = ImModPositive(g.TabFocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
+ if (g.TabFocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
+ g.TabFocusRequestCurrCounterTabStop = ImModPositive(g.TabFocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
+ g.TabFocusRequestNextWindow = NULL;
+ g.TabFocusRequestNextCounterRegular = g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
g.NavIdTabCounter = INT_MAX;
@@ -3904,7 +3941,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
// Modal windows prevents mouse from hovering behind them.
ImGuiWindow* modal_window = GetTopMostPopupModal();
- if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
+ if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindowDockTree, modal_window))
clear_hovered_windows = true;
// Disabled mouse?
@@ -3932,7 +3969,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
clear_hovered_windows = true;
if (clear_hovered_windows)
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
// Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app)
if (g.WantCaptureMouseNextFrame != -1)
@@ -3967,7 +4004,7 @@ void ImGui::NewFrame()
{
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
ImGuiContext& g = *GImGui;
-
+
// Remove pending delete hooks before frame start.
// This deferred removal avoid issues of removal while iterating the hook vector
for (int n = g.Hooks.Size - 1; n >= 0; n--)
@@ -4009,7 +4046,7 @@ void ImGui::NewFrame()
virtual_space.Add(g.Viewports[n]->GetMainRect());
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
- g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError);
+ g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
if (g.Style.AntiAliasedLines)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
@@ -4284,7 +4321,7 @@ void ImGui::Shutdown(ImGuiContext* context)
g.CurrentWindowStack.clear();
g.WindowsById.Clear();
g.NavWindow = NULL;
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
g.MovingWindow = NULL;
g.ColorStack.clear();
@@ -4516,15 +4553,15 @@ static void ImGui::EndFrameDrawDimmedBackgrounds()
// Choose a draw list that will be front-most across all our children
// In the unlikely case that the window wasn't made active we can't rely on its drawlist and skip rendering all-together.
ImGuiWindow* window = g.NavWindowingTargetAnim;
- ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindow)->DrawList;
+ ImDrawList* draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
draw_list->PushClipRectFullScreen();
// Docking: draw modal whitening background on other nodes of a same dock tree
// For CTRL+TAB within a docking node we need to render the dimming background in 8 steps
// (Because the root node renders the background in one shot, in order to avoid flickering when a child dock node is not submitted)
- if (window->RootWindowDockStop->DockIsActive)
- if (window->RootWindow != window->RootWindowDockStop)
- RenderRectFilledWithHole(draw_list, window->RootWindow->Rect(), window->RootWindowDockStop->Rect(), GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio), g.Style.WindowRounding);
+ if (window->RootWindow->DockIsActive)
+ if (window->RootWindowDockTree != window->RootWindow)
+ RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio), g.Style.WindowRounding);
// Draw navigation selection/windowing rectangle border
float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
@@ -4656,7 +4693,7 @@ void ImGui::Render()
// Add ImDrawList to render
ImGuiWindow* windows_to_render_top_most[2];
- windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
+ windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindowDockTree : NULL;
windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
for (int n = 0; n != g.Windows.Size; n++)
{
@@ -4781,14 +4818,13 @@ static void FindHoveredWindow()
if (hovered_window == NULL)
hovered_window = window;
- if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
+ if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree))
hovered_window_ignoring_moving_window = window;
if (hovered_window && hovered_window_ignoring_moving_window)
break;
}
g.HoveredWindow = hovered_window;
- g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
if (g.MovingWindow)
@@ -5077,6 +5113,8 @@ bool ImGui::IsItemFocused()
return true;
}
+// Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()!
+// Most widgets have specific reactions based on mouse-up/down state, mouse position etc.
bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
{
return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
@@ -5265,6 +5303,8 @@ void ImGui::EndChild()
// Not navigable into
ItemAdd(bb, 0);
}
+ if (g.HoveredWindow == window)
+ parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
}
g.WithinEndChild = false;
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
@@ -5385,9 +5425,10 @@ static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window)
return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window;
}
-static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
+static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& size_desired)
{
ImGuiContext& g = *GImGui;
+ ImVec2 new_size = size_desired;
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
{
// Using -1,-1 on either X/Y axis to preserve the current size.
@@ -5670,12 +5711,12 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
// Navigation resize (keyboard/gamepad)
- if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
+ if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindowDockTree == window)
{
ImVec2 nav_resize_delta;
- if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift)
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift)
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
- if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down);
if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
{
@@ -5721,7 +5762,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
float rounding = window->WindowRounding;
float border_size = window->WindowBorderSize;
if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
- window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
int border_held = window->ResizeBorderHeld;
if (border_held != -1)
@@ -5730,7 +5771,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
- window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), false, ImMax(2.0f, border_size)); // Thicker than usual
+ window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), 0, ImMax(2.0f, border_size)); // Thicker than usual
}
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
@@ -5800,7 +5841,7 @@ 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) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
+ window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
}
// Title bar
@@ -5809,7 +5850,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
- window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
+ window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
}
// Menu bar
@@ -5817,7 +5858,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{
ImRect menu_bar_rect = window->MenuBarRect();
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
- window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
+ window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
}
@@ -5955,12 +5996,12 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
{
window->ParentWindow = parent_window;
- window->RootWindow = window->RootWindowDockStop = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
+ window->RootWindow = window->RootWindowDockTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
{
- window->RootWindow = parent_window->RootWindow;
+ window->RootWindowDockTree = parent_window->RootWindowDockTree;
if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
- window->RootWindowDockStop = parent_window->RootWindowDockStop;
+ window->RootWindow = parent_window->RootWindow;
}
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
@@ -6076,9 +6117,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->PopupId = popup_ref.PopupId;
}
- if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow))
- window->NavLastIds[0] = 0;
-
// Update ->RootWindow and others pointers (before any possible call to FocusWindow)
if (first_begin_of_the_frame)
UpdateWindowParentAndRootLinks(window, flags, parent_window);
@@ -6232,7 +6270,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
window->Collapsed = !window->Collapsed;
MarkIniSettingsDirty(window);
- FocusWindow(window);
}
}
else
@@ -6402,9 +6439,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (window->WindowClass.ViewportFlagsOverrideClear)
viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
- // We also tell the backend that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha
+ // We can also tell the backend that clearing the platform window won't be necessary,
+ // as our window background is filling the viewport and we have disabled BgAlpha.
+ // FIXME: Work on support for per-viewport transparency (#2766)
if (!(flags & ImGuiWindowFlags_NoBackground))
- viewport_flags &= ~ImGuiViewportFlags_NoRendererClear;
+ viewport_flags |= ImGuiViewportFlags_NoRendererClear;
window->Viewport->Flags = viewport_flags;
}
@@ -6427,19 +6466,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
}
else if (window->ViewportOwned && g.PlatformIO.Monitors.Size > 0)
{
- if (window->Viewport->PlatformMonitor == -1)
- {
- // Fallback for "lost" window (e.g. a monitor disconnected): we move the window back over the main viewport
- const ImGuiViewport* main_viewport = GetMainViewport();
- SetWindowPos(window, main_viewport->Pos + style.DisplayWindowPadding, ImGuiCond_Always);
- }
- else
- {
- ImGuiPlatformMonitor& monitor = g.PlatformIO.Monitors[window->Viewport->PlatformMonitor];
- visibility_rect.Min = monitor.WorkPos + visibility_padding;
- visibility_rect.Max = monitor.WorkPos + monitor.WorkSize - visibility_padding;
- ClampWindowRect(window, visibility_rect);
- }
+ // Lost windows (e.g. a monitor disconnected) will naturally moved to the fallback/dummy monitor aka the main viewport.
+ const ImGuiPlatformMonitor* monitor = GetViewportPlatformMonitor(window->Viewport);
+ visibility_rect.Min = monitor->WorkPos + visibility_padding;
+ visibility_rect.Max = monitor->WorkPos + monitor->WorkSize - visibility_padding;
+ ClampWindowRect(window, visibility_rect);
}
}
window->Pos = ImFloor(window->Pos);
@@ -6582,7 +6613,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Draw modal or window list full viewport dimming background (for other viewports we'll render them in EndFrame)
ImGuiWindow* window_window_list = g.NavWindowingListWindow;
const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0;
- const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindow) || (window == window_window_list && window_window_list->Viewport != g.NavWindowingTargetAnim->Viewport));
+ const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindowDockTree) || (window == window_window_list && window_window_list->Viewport != g.NavWindowingTargetAnim->Viewport));
if (dim_bg_for_modal || dim_bg_for_window_list)
{
const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
@@ -6633,7 +6664,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
bb.Expand(-g.FontSize - 1.0f);
rounding = window->WindowRounding;
}
- window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f);
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, 0, 3.0f);
}
// UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
@@ -6706,7 +6737,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (want_focus)
{
FocusWindow(window);
- NavInitWindow(window, false);
+ NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls
}
// Close requested by platform window
@@ -6743,13 +6774,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Docking: Dragging a dockable window (or any of its child) turns it into a drag and drop source.
// We need to do this _before_ we overwrite window->DC.LastItemId below because BeginDockableDragDropSource() also overwrites it.
if ((g.MovingWindow == window) && (g.IO.ConfigDockingWithShift == g.IO.KeyShift))
- if ((window->RootWindow->Flags & ImGuiWindowFlags_NoDocking) == 0)
+ if ((window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
BeginDockableDragDropSource(window);
// Docking: Any dockable window can act as a target. For dock node hosts we call BeginDockableDragDropTarget() in DockNodeUpdate() instead.
if (g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
- if (g.MovingWindow == NULL || g.MovingWindow->RootWindow != window)
- if ((window == window->RootWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
+ if (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != window)
+ if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
BeginDockableDragDropTarget(window);
}
@@ -6823,6 +6854,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Update the Hidden flag
window->Hidden = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0) || (window->HiddenFramesForRenderOnly > 0);
+ // Disable inputs for requested number of frames
+ if (window->DisableInputsFrames > 0)
+ {
+ window->DisableInputsFrames--;
+ window->Flags |= ImGuiWindowFlags_NoInputs;
+ }
+
// Update the SkipItems flag, used to early out of all items functions (no layout required)
bool skip_items = false;
if (window->Collapsed || !window->Active || window->Hidden)
@@ -6894,7 +6932,7 @@ void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* current_front_window = g.Windows.back();
- if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
+ if (current_front_window == window || current_front_window->RootWindowDockTree == window) // Cheap early out (could be better)
return;
for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
if (g.Windows[i] == window)
@@ -6929,11 +6967,12 @@ void ImGui::FocusWindow(ImGuiWindow* window)
g.NavWindow = window;
if (window && g.NavDisableMouseHover)
g.NavMousePosDirty = true;
- g.NavInitRequest = false;
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
g.NavFocusScopeId = 0;
g.NavIdIsAlive = false;
g.NavLayer = ImGuiNavLayer_Main;
+ g.NavInitRequest = g.NavMoveRequest = false;
+ NavUpdateAnyRequestFlag();
//IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
}
@@ -6941,9 +6980,9 @@ void ImGui::FocusWindow(ImGuiWindow* window)
ClosePopupsOverWindow(window, false);
// Move the root window to the top of the pile
- IM_ASSERT(window == NULL || window->RootWindow != NULL);
- ImGuiWindow* focus_front_window = window ? window->RootWindowDockStop : NULL;
- ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
+ IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
+ ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
+ ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
@@ -6951,7 +6990,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
// - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run.
// - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId)
// - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window.
- if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindowDockStop != focus_front_window)
+ if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
if (!g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
ClearActiveID();
@@ -6985,7 +7024,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
{
// We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
ImGuiWindow* window = g.WindowsFocusOrder[i];
- if (window != ignore_window && window->WasActive && window->RootWindowDockStop == window)
+ if (window != ignore_window && window->WasActive && window->RootWindow == window)
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
{
// FIXME-DOCK: This is failing (lagging by one frame) for docked windows.
@@ -7000,6 +7039,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
FocusWindow(NULL);
}
+// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
void ImGui::SetCurrentFont(ImFont* font)
{
ImGuiContext& g = *GImGui;
@@ -7094,7 +7134,7 @@ void ImGui::PopTextWrapPos()
bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
{
- if (window->RootWindow == potential_parent)
+ if (window->RootWindowDockTree == potential_parent)
return true;
while (window != NULL)
{
@@ -7123,30 +7163,28 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
ImGuiContext& g = *GImGui;
+ if (g.HoveredWindow == NULL)
+ return false;
- if (flags & ImGuiHoveredFlags_AnyWindow)
- {
- if (g.HoveredWindow == NULL)
- return false;
- }
- else
+ if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
{
+ ImGuiWindow* window = g.CurrentWindow;
switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows))
{
case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows:
- if (g.HoveredWindow == NULL || g.HoveredWindow->RootWindowDockStop != g.CurrentWindow->RootWindowDockStop)
+ if (g.HoveredWindow->RootWindow != window->RootWindow)
return false;
break;
case ImGuiHoveredFlags_RootWindow:
- if (g.HoveredWindow != g.CurrentWindow->RootWindowDockStop)
+ if (g.HoveredWindow != window->RootWindow)
return false;
break;
case ImGuiHoveredFlags_ChildWindows:
- if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow))
+ if (!IsWindowChildOf(g.HoveredWindow, window))
return false;
break;
default:
- if (g.HoveredWindow != g.CurrentWindow)
+ if (g.HoveredWindow != window)
return false;
break;
}
@@ -7171,9 +7209,9 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows))
{
case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows:
- return g.NavWindow && g.NavWindow->RootWindowDockStop == g.CurrentWindow->RootWindowDockStop;
+ return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
case ImGuiFocusedFlags_RootWindow:
- return g.NavWindow == g.CurrentWindow->RootWindowDockStop;
+ return g.NavWindow == g.CurrentWindow->RootWindow;
case ImGuiFocusedFlags_ChildWindows:
return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow);
default:
@@ -7198,7 +7236,7 @@ bool ImGui::IsWindowDocked()
// If you want a window to never be focused, you may use the e.g. NoInputs flag.
bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
{
- return window->WasActive && window == window->RootWindowDockStop && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
+ return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
}
float ImGui::GetWindowWidth()
@@ -7521,9 +7559,9 @@ void ImGui::SetKeyboardFocusHere(int offset)
IM_ASSERT(offset >= -1); // -1 is allowed but not below
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
- g.FocusRequestNextWindow = window;
- g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset;
- g.FocusRequestNextCounterTabStop = INT_MAX;
+ g.TabFocusRequestNextWindow = window;
+ g.TabFocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset;
+ g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
void ImGui::SetItemDefaultFocus()
@@ -7690,7 +7728,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
- IM_ASSERT(g.Style.CircleSegmentMaxError > 0.0f && "Invalid style setting!");
+ IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
@@ -8303,6 +8341,7 @@ void ImGui::BeginGroup()
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
+ group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.EmitItem = true;
@@ -8356,6 +8395,11 @@ void ImGui::EndGroup()
window->DC.LastItemId = g.ActiveIdPreviousFrame;
window->DC.LastItemRect = group_bb;
+ // Forward Hovered flag
+ const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
+ if (group_contains_curr_hovered_id)
+ window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
+
// Forward Edited flag
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
@@ -8765,12 +8809,12 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
// Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow)
// - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3:
// Window -> Popup1 -> Popup2 -> Popup3
- // - Each popups may contain child windows, which is why we compare ->RootWindow!
+ // - Each popups may contain child windows, which is why we compare ->RootWindowDockTree!
// Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
bool ref_window_is_descendent_of_popup = false;
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
- if (popup_window->RootWindow == ref_window->RootWindow)
+ if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree)
{
ref_window_is_descendent_of_popup = true;
break;
@@ -9135,26 +9179,19 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
//-----------------------------------------------------------------------------
-// FIXME-NAV: The existence of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing,
-// and needs some explanation or serious refactoring.
-void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id)
+// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked.
+void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
{
ImGuiContext& g = *GImGui;
- IM_ASSERT(g.NavWindow);
- IM_ASSERT(nav_layer == 0 || nav_layer == 1);
+ IM_ASSERT(g.NavWindow != NULL);
+ IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
g.NavId = id;
+ g.NavLayer = (ImGuiNavLayer)nav_layer;
g.NavFocusScopeId = focus_scope_id;
g.NavWindow->NavLastIds[nav_layer] = id;
-}
-
-void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
-{
- ImGuiContext& g = *GImGui;
- SetNavID(id, nav_layer, focus_scope_id);
g.NavWindow->NavRectRel[nav_layer] = rect_rel;
- g.NavMousePosDirty = true;
- g.NavDisableHighlight = false;
- g.NavDisableMouseHover = true;
+ //g.NavDisableHighlight = false;
+ //g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
@@ -9453,7 +9490,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
{
ImGuiWindow* parent = nav_window;
- while (parent && parent->RootWindowDockStop != parent && (parent->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
parent = parent->ParentWindow;
if (parent && parent != nav_window)
parent->NavLastChildNavWindow = nav_window;
@@ -9471,17 +9508,23 @@ static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
return window;
}
-static void NavRestoreLayer(ImGuiNavLayer layer)
+void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
{
ImGuiContext& g = *GImGui;
- g.NavLayer = layer;
- if (layer == 0)
- g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow);
+ if (layer == ImGuiNavLayer_Main)
+ g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
ImGuiWindow* window = g.NavWindow;
if (window->NavLastIds[layer] != 0)
- ImGui::SetNavIDWithRectRel(window->NavLastIds[layer], layer, 0, g.NavWindow->NavRectRel[layer]);
+ {
+ SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+ }
else
- ImGui::NavInitWindow(window, true);
+ {
+ g.NavLayer = layer;
+ NavInitWindow(window, true);
+ }
}
static inline void ImGui::NavUpdateAnyRequestFlag()
@@ -9495,16 +9538,17 @@ static inline void ImGui::NavUpdateAnyRequestFlag()
// This needs to be called before we submit any widget (aka in or before Begin)
void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
{
+ // FIXME: ChildWindow test here is wrong for docking
ImGuiContext& g = *GImGui;
IM_ASSERT(window == g.NavWindow);
bool init_for_nav = false;
if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
- if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
+ if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
init_for_nav = true;
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
if (init_for_nav)
{
- SetNavID(0, g.NavLayer, 0);
+ SetNavID(0, g.NavLayer, 0, ImRect());
g.NavInitRequest = true;
g.NavInitRequestFromMove = false;
g.NavInitResultId = 0;
@@ -9592,17 +9636,17 @@ static void ImGui::NavUpdate()
// (do it before we map Keyboard input!)
bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
- if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_NavGamepad)
+ if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
{
if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
|| io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f)
- g.NavInputSource = ImGuiInputSource_NavGamepad;
+ g.NavInputSource = ImGuiInputSource_Gamepad;
}
// Update Keyboard->Nav inputs mapping
if (nav_keyboard_active)
{
- #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } } while (0)
+ #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
@@ -9623,7 +9667,7 @@ static void ImGui::NavUpdate()
io.NavInputsDownDuration[i] = (io.NavInputs[i] > 0.0f) ? (io.NavInputsDownDuration[i] < 0.0f ? 0.0f : io.NavInputsDownDuration[i] + io.DeltaTime) : -1.0f;
// Process navigation init request (select first/default focus)
- if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove))
+ if (g.NavInitResultId != 0)
NavUpdateInitResult();
g.NavInitRequest = false;
g.NavInitRequestFromMove = false;
@@ -9648,13 +9692,11 @@ static void ImGui::NavUpdate()
{
// Set mouse position given our knowledge of the navigated item position from last frame
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
- {
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
{
io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
io.WantSetMousePos = true;
}
- }
g.NavMousePosDirty = false;
}
g.NavIdIsAlive = false;
@@ -9683,18 +9725,15 @@ static void ImGui::NavUpdate()
if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel))
ClearActiveID();
}
- else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow && g.NavWindow != g.NavWindow->RootWindowDockStop)
+ else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
{
// Exit child window
ImGuiWindow* child_window = g.NavWindow;
ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
IM_ASSERT(child_window->ChildId != 0);
+ ImRect child_rect = child_window->Rect();
FocusWindow(parent_window);
- SetNavID(child_window->ChildId, 0, 0);
- // Reassigning with same value, we're being explicit here.
- g.NavIdIsAlive = false; // -V1048
- if (g.NavDisableMouseHover)
- g.NavMousePosDirty = true;
+ SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, ImRect(child_rect.Min - parent_window->Pos, child_rect.Max - parent_window->Pos));
}
else if (g.OpenPopupStack.Size > 0)
{
@@ -9821,7 +9860,7 @@ static void ImGui::NavUpdate()
// When using gamepad, we project the reference nav bounding box into window visible area.
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
// (can't focus a visible object like we can with the mouse).
- if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_NavGamepad && g.NavLayer == ImGuiNavLayer_Main)
+ if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main)
{
ImGuiWindow* window = g.NavWindow;
ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
@@ -9863,11 +9902,12 @@ static void ImGui::NavUpdateInitResult()
// Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name);
+ SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
if (g.NavInitRequestFromMove)
- SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
- else
- SetNavID(g.NavInitResultId, g.NavLayer, 0);
- g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel;
+ {
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+ }
}
// Apply result from previous frame navigation directional move request
@@ -9930,7 +9970,9 @@ static void ImGui::NavUpdateMoveResult()
g.NavJustMovedToKeyMods = g.NavMoveRequestKeyMods;
}
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
- SetNavIDWithRectRel(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
+ SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
}
// Handle PageUp/PageDown/Home/End keys
@@ -10131,15 +10173,15 @@ static void ImGui::NavUpdateWindowing()
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
{
- g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindowDockStop;
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
- g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
+ g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
}
// Gamepad update
g.NavWindowingTimer += g.IO.DeltaTime;
- if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad)
{
// Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
@@ -10165,7 +10207,7 @@ static void ImGui::NavUpdateWindowing()
}
// Keyboard: Focus
- if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard)
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard)
{
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
@@ -10187,15 +10229,15 @@ static void ImGui::NavUpdateWindowing()
if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
{
ImVec2 move_delta;
- if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift)
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && !g.IO.KeyShift)
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
- if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
if (move_delta.x != 0.0f || move_delta.y != 0.0f)
{
const float NAV_MOVE_SPEED = 800.0f;
const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well
- ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow;
+ ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindowDockTree;
SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always);
MarkIniSettingsDirty(moving_window);
g.NavDisableMouseHover = true;
@@ -10203,7 +10245,7 @@ static void ImGui::NavUpdateWindowing()
}
// Apply final focus
- if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindowDockStop))
+ if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
{
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
ClearActiveID();
@@ -10245,11 +10287,11 @@ static void ImGui::NavUpdateWindowing()
g.NavDisableHighlight = false;
g.NavDisableMouseHover = true;
- // When entering a regular menu bar with the Alt key, we always reinitialize the navigation ID. It however persist on docking tab tabs.
+ // Reinitialize navigation when entering menu bar with the Alt key. We make it persist on Docking Tab Bars.
const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main;
const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
- g.NavWindow->NavLastIds[ImGuiNavLayer_Menu] = 0;
+ g.NavWindow->NavLastIds[new_nav_layer] = 0;
NavRestoreLayer(new_nav_layer);
}
}
@@ -10315,27 +10357,45 @@ void ImGui::ClearDragDrop()
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
}
-// Call when current ID is active.
// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
+// If the item has an identifier:
+// - This assume/require the item to be activated (typically via ButtonBehavior).
+// - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with another button.
+// - We then pull and use the mouse button that was used to activate the item and use it to carry on the drag.
+// If the item has no identifier:
+// - Currently always assume left mouse button.
bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
+ // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button,
+ // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic).
+ ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
+
bool source_drag_active = false;
ImGuiID source_id = 0;
ImGuiID source_parent_id = 0;
- ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
if (!(flags & ImGuiDragDropFlags_SourceExtern))
{
source_id = window->DC.LastItemId;
- if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
- return false;
- if (g.IO.MouseDown[mouse_button] == false)
- return false;
-
- if (source_id == 0)
+ if (source_id != 0)
+ {
+ // Common path: items with ID
+ if (g.ActiveId != source_id)
+ return false;
+ if (g.ActiveIdMouseButton != -1)
+ mouse_button = g.ActiveIdMouseButton;
+ if (g.IO.MouseDown[mouse_button] == false)
+ return false;
+ g.ActiveIdAllowOverlap = false;
+ }
+ else
{
+ // Uncommon path: items without ID
+ if (g.IO.MouseDown[mouse_button] == false)
+ return false;
+
// If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
// A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
@@ -10362,10 +10422,6 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
g.ActiveIdAllowOverlap = is_hovered;
}
- else
- {
- g.ActiveIdAllowOverlap = false;
- }
if (g.ActiveId != source_id)
return false;
source_parent_id = window->IDStack.back();
@@ -10489,7 +10545,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
ImGuiWindow* window = g.CurrentWindow;
ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
- if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
+ if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
return false;
IM_ASSERT(id != 0);
if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
@@ -10518,7 +10574,7 @@ bool ImGui::BeginDragDropTarget()
if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
return false;
ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
- if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
+ if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
return false;
const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
@@ -10568,11 +10624,11 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
{
- // FIXME-DRAG: Settle on a proper default visuals for drop target.
+ // FIXME-DRAGDROP: Settle on a proper default visuals for drop target.
r.Expand(3.5f);
bool push_clip_rect = !window->ClipRect.Contains(r);
if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1));
- window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
+ window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
if (push_clip_rect) window->DrawList->PopClipRect();
}
@@ -10607,14 +10663,8 @@ void ImGui::EndDragDropTarget()
//-----------------------------------------------------------------------------
// Pass text data straight to log (without being displayed)
-void ImGui::LogText(const char* fmt, ...)
+static inline void LogTextV(ImGuiContext& g, const char* fmt, va_list args)
{
- ImGuiContext& g = *GImGui;
- if (!g.LogEnabled)
- return;
-
- va_list args;
- va_start(args, fmt);
if (g.LogFile)
{
g.LogBuffer.Buf.resize(0);
@@ -10625,9 +10675,29 @@ void ImGui::LogText(const char* fmt, ...)
{
g.LogBuffer.appendfv(fmt, args);
}
+}
+
+void ImGui::LogText(const char* fmt, ...)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+ LogTextV(g, fmt, args);
va_end(args);
}
+void ImGui::LogTextV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ LogTextV(g, fmt, args);
+}
+
// Internal version that takes a position to decide on newline placement and pad items according to their depth.
// We split text into individual lines to add current tree level padding
// FIXME: This code is a little complicated perhaps, considering simplifying the whole system.
@@ -11157,7 +11227,6 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
buf->appendf("Collapsed=%d\n", settings->Collapsed);
if (settings->DockId != 0)
{
- // Write DockId as 4 digits if possible. Automatic DockId are small numbers, but full explicit DockSpace() are full ImGuiID range.
if (settings->DockOrder == -1)
buf->appendf("DockId=0x%08X\n", settings->DockId);
else
@@ -11485,6 +11554,17 @@ static void ImGui::UpdateViewportsNewFrame()
viewport->DpiScale = new_dpi_scale;
}
+ // Update fallback monitor
+ if (g.PlatformIO.Monitors.Size == 0)
+ {
+ ImGuiPlatformMonitor* monitor = &g.FallbackMonitor;
+ monitor->MainPos = main_viewport->Pos;
+ monitor->MainSize = main_viewport->Size;
+ monitor->WorkPos = main_viewport->WorkPos;
+ monitor->WorkSize = main_viewport->WorkSize;
+ monitor->DpiScale = main_viewport->DpiScale;
+ }
+
if (!viewports_enabled)
{
g.MouseViewport = main_viewport;
@@ -11567,7 +11647,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const
flags |= ImGuiViewportFlags_IsPlatformWindow;
if (window != NULL)
{
- if (g.MovingWindow && g.MovingWindow->RootWindow == window)
+ if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window)
flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
flags |= ImGuiViewportFlags_NoInputs;
@@ -11680,7 +11760,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
}
- else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid())
+ else if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
{
if (window->Viewport != NULL && window->Viewport->Window == window)
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
@@ -11698,7 +11778,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
if (window->Viewport == NULL)
if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
-
+
// Mark window as allowed to protrude outside of its viewport and into the current monitor
if (!lock_viewport)
{
@@ -11961,6 +12041,17 @@ static void ImGui::UpdateViewportPlatformMonitor(ImGuiViewportP* viewport)
viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
}
+// Return value is always != NULL, but don't hold on it across frames.
+const ImGuiPlatformMonitor* ImGui::GetViewportPlatformMonitor(ImGuiViewport* viewport_p)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)viewport_p;
+ int monitor_idx = viewport->PlatformMonitor;
+ if (monitor_idx >= 0 || monitor_idx < g.PlatformIO.Monitors.Size)
+ return &g.PlatformIO.Monitors[monitor_idx];
+ return &g.FallbackMonitor;
+}
+
void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
{
ImGuiContext& g = *GImGui;
@@ -12120,14 +12211,14 @@ struct ImGuiDockNodeSettings
ImGuiID ID;
ImGuiID ParentNodeId;
ImGuiID ParentWindowId;
- ImGuiID SelectedWindowId;
+ ImGuiID SelectedTabId;
signed char SplitAxis;
char Depth;
ImGuiDockNodeFlags Flags; // NB: We save individual flags one by one in ascii format (ImGuiDockNodeFlags_SavedFlagsMask_)
ImVec2ih Pos;
ImVec2ih Size;
ImVec2ih SizeRef;
- ImGuiDockNodeSettings() { ID = ParentNodeId = ParentWindowId = SelectedWindowId = 0; SplitAxis = ImGuiAxis_None; Depth = 0; Flags = ImGuiDockNodeFlags_None; }
+ ImGuiDockNodeSettings() { memset(this, 0, sizeof(*this)); SplitAxis = ImGuiAxis_None; }
};
//-----------------------------------------------------------------------------
@@ -12327,8 +12418,8 @@ void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
{
if (hovered_window->DockNodeAsHost)
g.HoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost, g.IO.MousePos);
- else if (hovered_window->RootWindowDockStop->DockNode)
- g.HoveredDockNode = hovered_window->RootWindowDockStop->DockNode;
+ else if (hovered_window->RootWindow->DockNode)
+ g.HoveredDockNode = hovered_window->RootWindow->DockNode;
}
// Process Docking requests
@@ -12504,7 +12595,7 @@ static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDoc
node->ParentNode->ChildNodes[0] = node;
else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
node->ParentNode->ChildNodes[1] = node;
- node->SelectedTabId = settings->SelectedWindowId;
+ node->SelectedTabId = settings->SelectedTabId;
node->SplitAxis = (ImGuiAxis)settings->SplitAxis;
node->LocalFlags |= (settings->Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
@@ -12838,7 +12929,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
AuthorityForViewport = ImGuiDataAuthority_Auto;
IsVisible = true;
- IsFocused = HasCloseButton = HasWindowMenuButton = EnableCloseButton = false;
+ IsFocused = HasCloseButton = HasWindowMenuButton = false;
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false;
MarkedForPosSizeWrite = false;
}
@@ -12924,7 +13015,7 @@ static void ImGui::DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window
{
ImGuiContext& g = *GImGui;
IM_ASSERT(window->DockNode == node);
- //IM_ASSERT(window->RootWindow == node->HostWindow);
+ //IM_ASSERT(window->RootWindowDockTree == node->HostWindow);
//IM_ASSERT(window->LastFrameActive < g.FrameCount); // We may call this from Begin()
IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
IMGUI_DEBUG_LOG_DOCKING("DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
@@ -13148,6 +13239,7 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
}
else
{
+ // FIXME-DOCKING: Missing policies for conflict resolution, hence the "Experimental" tag on this.
node->LocalFlags &= ~window->WindowClass.DockNodeFlagsOverrideClear;
node->LocalFlags |= window->WindowClass.DockNodeFlagsOverrideSet;
}
@@ -13272,7 +13364,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
node->WantCloseAll = false;
node->WantCloseTabId = 0;
- node->HasCloseButton = node->HasWindowMenuButton = node->EnableCloseButton = false;
+ node->HasCloseButton = node->HasWindowMenuButton = false;
node->LastFrameActive = g.FrameCount;
if (node->WantMouseMove && node->Windows.Size == 1)
@@ -13307,6 +13399,19 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
+ // Decide if the node will have a close button and a window menu button
+ node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
+ node->HasCloseButton = false;
+ for (int window_n = 0; window_n < node->Windows.Size; window_n++)
+ {
+ // FIXME-DOCK: Setting DockIsActive here means that for single active window in a leaf node, DockIsActive will be cleared until the next Begin() call.
+ ImGuiWindow* window = node->Windows[window_n];
+ node->HasCloseButton |= window->HasCloseButton;
+ window->DockIsActive = (node->Windows.Size > 1);
+ }
+ if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
+ node->HasCloseButton = false;
+
// Bind or create host window
ImGuiWindow* host_window = NULL;
bool beginned_into_host_window = false;
@@ -13314,25 +13419,11 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
{
// [Explicit root dockspace node]
IM_ASSERT(node->HostWindow);
- node->EnableCloseButton = false;
- node->HasCloseButton = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
- node->HasWindowMenuButton = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
host_window = node->HostWindow;
}
else
{
// [Automatic root or child nodes]
- node->EnableCloseButton = false;
- node->HasCloseButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
- node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
- for (int window_n = 0; window_n < node->Windows.Size; window_n++)
- {
- // FIXME-DOCK: Setting DockIsActive here means that for single active window in a leaf node, DockIsActive will be cleared until the next Begin() call.
- ImGuiWindow* window = node->Windows[window_n];
- window->DockIsActive = (node->Windows.Size > 1);
- node->EnableCloseButton |= window->HasCloseButton;
- }
-
if (node->IsRootNode() && node->IsVisible)
{
ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
@@ -13402,8 +13493,8 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (node->IsSplitNode())
IM_ASSERT(node->TabBar == NULL);
if (node->IsRootNode())
- if (g.NavWindow && g.NavWindow->RootWindowDockStop->DockNode && g.NavWindow->RootWindowDockStop->ParentWindow == host_window)
- node->LastFocusedNodeId = g.NavWindow->RootWindowDockStop->DockNode->ID;
+ if (g.NavWindow && g.NavWindow->RootWindow->DockNode && g.NavWindow->RootWindow->ParentWindow == host_window)
+ node->LastFocusedNodeId = g.NavWindow->RootWindow->DockNode->ID;
// We need to draw a background at the root level if requested by ImGuiDockNodeFlags_PassthruCentralNode, but we will only know the correct pos/size
// _after_ processing the resizing splitters. So we are using the DrawList channel splitting facility to submit drawing primitives out of order!
@@ -13483,7 +13574,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
// Draw payload drop target
if (host_window && node->IsVisible)
- if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindow != host_window))
+ if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != host_window))
BeginDockableDragDropTarget(host_window);
// We update this after DockNodeUpdateTabBar()
@@ -13564,7 +13655,7 @@ bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
PushOverrideID(node->ID);
bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags, node);
IM_UNUSED(ret);
- IM_ASSERT(ret);
+ IM_ASSERT(ret);
return true;
}
@@ -13592,7 +13683,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
ImGuiDockNode* root_node = DockNodeGetRootNode(node);
if (g.NavWindowingTarget)
is_focused = (g.NavWindowingTarget->DockNode == node);
- else if (g.NavWindow && g.NavWindow->RootWindowForTitleBarHighlight == host_window->RootWindow && root_node->LastFocusedNodeId == node->ID)
+ else if (g.NavWindow && g.NavWindow->RootWindowForTitleBarHighlight == host_window->RootWindowDockTree && root_node->LastFocusedNodeId == node->ID)
is_focused = true;
// Hidden tab bar will show a triangle on the upper-left (in Begin)
@@ -13638,7 +13729,6 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
- const bool has_close_button = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
// In a dock node, the Collapse Button turns into the Window Menu button.
// FIXME-DOCK FIXME-OPT: Could we recycle popups id across multiple dock nodes?
@@ -13659,7 +13749,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
for (int window_n = 0; window_n < node->Windows.Size; window_n++)
{
ImGuiWindow* window = node->Windows[window_n];
- if (g.NavWindow && g.NavWindow->RootWindowDockStop == window)
+ if (g.NavWindow && g.NavWindow->RootWindow == window)
tab_bar->SelectedTabId = window->ID;
if (TabBarFindTabByID(tab_bar, window->ID) == NULL)
TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
@@ -13669,7 +13759,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
if (is_focused)
node->LastFrameFocused = g.FrameCount;
ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
- host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, ImDrawCornerFlags_Top);
+ host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, ImDrawFlags_RoundCornersTop);
// Docking/Collapse button
if (has_window_menu_button)
@@ -13748,7 +13838,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
window->DockTabItemRect = host_window->DC.LastItemRect;
// Update navigation ID on menu layer
- if (g.NavWindow && g.NavWindow->RootWindowDockStop == window && (window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
+ if (g.NavWindow && g.NavWindow->RootWindow == window && (window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
host_window->NavLastIds[1] = window->ID;
}
}
@@ -13764,12 +13854,15 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Close button (after VisibleWindow was updated)
// Note that VisibleWindow may have been overrided by CTRL+Tabbing, so VisibleWindow->ID may be != from tab_bar->SelectedTabId
- if (has_close_button && node->VisibleWindow)
+ const bool close_button_is_enabled = node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
+ const bool close_button_is_visible = node->HasCloseButton;
+ //const bool close_button_is_visible = close_button_is_enabled; // Most people would expect this behavior of not even showing the button (leaving a hole since we can't claim that space as other windows in the tba bar have one)
+ if (close_button_is_visible)
{
- if (!node->VisibleWindow->HasCloseButton)
+ if (!close_button_is_enabled)
{
PushItemFlag(ImGuiItemFlags_Disabled, true);
- PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.5f));
+ PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.4f));
}
const float button_sz = g.FontSize;
if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x * 2.0f - button_sz, 0.0f)))
@@ -13780,7 +13873,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
}
//if (IsItemActive())
// focus_tab_id = tab_bar->SelectedTabId;
- if (!node->VisibleWindow->HasCloseButton)
+ if (!close_button_is_enabled)
{
PopStyleColor();
PopItemFlag();
@@ -15337,7 +15430,7 @@ void ImGui::BeginDockableDragDropSource(ImGuiWindow* window)
IM_ASSERT(g.MovingWindow == window);
window->DC.LastItemId = window->MoveId;
- window = window->RootWindow;
+ window = window->RootWindowDockTree;
IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
bool is_drag_docking = (g.IO.ConfigDockingWithShift) || ImRect(0, 0, window->SizeFull.x, GetFrameHeight()).Contains(g.ActiveIdClickOffset);
if (is_drag_docking && BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers | ImGuiDragDropFlags_SourceAutoExpirePayload))
@@ -15356,7 +15449,7 @@ void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
ImGuiContext* ctx = GImGui;
ImGuiContext& g = *ctx;
- //IM_ASSERT(window->RootWindow == window); // May also be a DockSpace
+ //IM_ASSERT(window->RootWindowDockTree == window); // May also be a DockSpace
IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
if (!g.DragDropActive)
return;
@@ -15550,7 +15643,7 @@ static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettings
if (sscanf(line, " HiddenTabBar=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
if (sscanf(line, " NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
if (sscanf(line, " NoCloseButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoCloseButton; }
- if (sscanf(line, " Selected=0x%08X%n", &node.SelectedWindowId,&r) == 1) { line += r; }
+ if (sscanf(line, " Selected=0x%08X%n", &node.SelectedTabId,&r) == 1) { line += r; }
if (node.ParentNodeId != 0)
if (ImGuiDockNodeSettings* parent_settings = DockSettingsFindNodeSettings(ctx, node.ParentNodeId))
node.Depth = parent_settings->Depth + 1;
@@ -15564,7 +15657,7 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
node_settings.ID = node->ID;
node_settings.ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
node_settings.ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) ? node->HostWindow->ParentWindow->ID : 0;
- node_settings.SelectedWindowId = node->SelectedTabId;
+ node_settings.SelectedTabId = node->SelectedTabId;
node_settings.SplitAxis = (signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
node_settings.Depth = (char)depth;
node_settings.Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
@@ -15630,8 +15723,8 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
buf->appendf(" NoWindowMenuButton=1");
if (node_settings->Flags & ImGuiDockNodeFlags_NoCloseButton)
buf->appendf(" NoCloseButton=1");
- if (node_settings->SelectedWindowId)
- buf->appendf(" Selected=0x%08X", node_settings->SelectedWindowId);
+ if (node_settings->SelectedTabId)
+ buf->appendf(" Selected=0x%08X", node_settings->SelectedTabId);
#if IMGUI_DEBUG_INI_SETTINGS
// [DEBUG] Include comments in the .ini file to ease debugging
@@ -15992,7 +16085,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
Indent();
char buf[128];
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
@@ -16007,7 +16100,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
}
}
else
@@ -16016,7 +16109,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
- GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
}
}
Unindent();
@@ -16192,14 +16285,14 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
ImGuiDockNodeSettings* settings = &dc->NodesSettings[n];
const char* selected_tab_name = NULL;
- if (settings->SelectedWindowId)
+ if (settings->SelectedTabId)
{
- if (ImGuiWindow* window = FindWindowByID(settings->SelectedWindowId))
+ if (ImGuiWindow* window = FindWindowByID(settings->SelectedTabId))
selected_tab_name = window->Name;
- else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedWindowId))
+ else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedTabId))
selected_tab_name = window_settings->GetName();
}
- BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId, settings->SelectedWindowId, selected_tab_name ? selected_tab_name : settings->SelectedWindowId ? "N/A" : "");
+ BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId, settings->SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ? "N/A" : "");
}
TreePop();
}
@@ -16221,7 +16314,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("WINDOWING");
Indent();
Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
- Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
+ Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindowDockTree->Name : "NULL");
Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
Text("HoveredDockNode: 0x%08X", g.HoveredDockNode ? g.HoveredDockNode->ID : 0);
Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
@@ -16293,7 +16386,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
- draw_list->AddRect(r.Min, r.Max, col, 0.0f, ~0, thickness);
+ draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
}
}
else
@@ -16480,7 +16573,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
{
ImDrawListFlags backup_flags = fg_draw_list->Flags;
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
- fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f);
+ fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
fg_draw_list->Flags = backup_flags;
}
}
@@ -16507,7 +16600,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
for (int n = 0; n < 3; n++, idx_n++)
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
if (show_mesh)
- out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles
+ out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
}
// Draw bounding boxes
if (show_aabb)
@@ -16650,10 +16743,10 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
BulletText("DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
if (window->DockNode || window->DockNodeAsHost)
DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ? "DockNodeAsHost" : "DockNode");
- if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
- if (window->RootWindowDockStop != window->RootWindow) { DebugNodeWindow(window->RootWindowDockStop, "RootWindowDockStop"); }
- if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
- if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
+ if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
+ if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree, "RootWindowDockTree"); }
+ if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
+ if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
{
for (int n = 0; n < window->ColumnsStorage.Size; n++)