|
@@ -1068,7 +1068,6 @@ static void RenderWindowDecorations(ImGuiWindow* window, const ImRec
|
|
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
|
|
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
|
|
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
|
|
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
|
|
static void RenderDimmedBackgrounds();
|
|
static void RenderDimmedBackgrounds();
|
|
-static ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
|
|
|
|
|
|
|
|
// Viewports
|
|
// Viewports
|
|
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
|
|
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
|
|
@@ -3828,7 +3827,10 @@ static void SetCurrentWindow(ImGuiWindow* window)
|
|
g.CurrentWindow = window;
|
|
g.CurrentWindow = window;
|
|
g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
|
|
g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
|
|
if (window)
|
|
if (window)
|
|
|
|
+ {
|
|
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
|
|
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
|
|
|
|
+ ImGui::NavUpdateCurrentWindowIsScrollPushableX();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void ImGui::GcCompactTransientMiscBuffers()
|
|
void ImGui::GcCompactTransientMiscBuffers()
|
|
@@ -3993,7 +3995,7 @@ bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flag
|
|
|
|
|
|
// Inhibit hover unless the window is within the stack of our modal/popup
|
|
// Inhibit hover unless the window is within the stack of our modal/popup
|
|
if (want_inhibit)
|
|
if (want_inhibit)
|
|
- if (!ImGui::IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
|
|
|
|
|
|
+ if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4448,10 +4450,10 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|
if (g.HoveredIdDisabled)
|
|
if (g.HoveredIdDisabled)
|
|
g.MovingWindow = NULL;
|
|
g.MovingWindow = NULL;
|
|
}
|
|
}
|
|
- else if (root_window == NULL && g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
|
|
|
|
|
|
+ else if (root_window == NULL && g.NavWindow != NULL)
|
|
{
|
|
{
|
|
// Clicking on void disable focus
|
|
// Clicking on void disable focus
|
|
- FocusWindow(NULL);
|
|
|
|
|
|
+ FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4808,7 +4810,7 @@ void ImGui::NewFrame()
|
|
|
|
|
|
// Closing the focused window restore focus to the first active root window in descending z-order
|
|
// Closing the focused window restore focus to the first active root window in descending z-order
|
|
if (g.NavWindow && !g.NavWindow->WasActive)
|
|
if (g.NavWindow && !g.NavWindow->WasActive)
|
|
- FocusTopMostWindowUnderOne(NULL, NULL, NULL);
|
|
|
|
|
|
+ FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
|
|
|
|
|
|
// No window should be open at the beginning of the frame.
|
|
// No window should be open at the beginning of the frame.
|
|
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
|
|
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
|
|
@@ -5579,7 +5581,8 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|
parent_window->DC.CursorPos = child_window->Pos;
|
|
parent_window->DC.CursorPos = child_window->Pos;
|
|
|
|
|
|
// Process navigation-in immediately so NavInit can run on first frame
|
|
// Process navigation-in immediately so NavInit can run on first frame
|
|
- if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavHasScroll))
|
|
|
|
|
|
+ // Can enter a child if (A) it has navigatable items or (B) it can be scrolled.
|
|
|
|
+ if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
|
|
{
|
|
{
|
|
FocusWindow(child_window);
|
|
FocusWindow(child_window);
|
|
NavInitWindow(child_window, false);
|
|
NavInitWindow(child_window, false);
|
|
@@ -5626,7 +5629,7 @@ void ImGui::EndChild()
|
|
ImGuiWindow* parent_window = g.CurrentWindow;
|
|
ImGuiWindow* parent_window = g.CurrentWindow;
|
|
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
|
|
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
|
|
ItemSize(sz);
|
|
ItemSize(sz);
|
|
- if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
|
|
|
|
|
|
+ if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavWindowHasScrollY) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
|
|
{
|
|
{
|
|
ItemAdd(bb, window->ChildId);
|
|
ItemAdd(bb, window->ChildId);
|
|
RenderNavHighlight(bb, window->ChildId);
|
|
RenderNavHighlight(bb, window->ChildId);
|
|
@@ -6437,7 +6440,10 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
|
|
// - Window // .. returns Modal2
|
|
// - Window // .. returns Modal2
|
|
// - Window // .. returns Modal2
|
|
// - Window // .. returns Modal2
|
|
// - Modal2 // .. returns Modal2
|
|
// - Modal2 // .. returns Modal2
|
|
-static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
|
|
|
|
+// Notes:
|
|
|
|
+// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL.
|
|
|
|
+// Only difference is here we check for ->Active/WasActive but it may be unecessary.
|
|
|
|
+ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
if (g.OpenPopupStack.Size <= 0)
|
|
if (g.OpenPopupStack.Size <= 0)
|
|
@@ -6451,6 +6457,8 @@ static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
continue;
|
|
continue;
|
|
if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
|
|
if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
|
|
continue;
|
|
continue;
|
|
|
|
+ if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click.
|
|
|
|
+ return popup_window;
|
|
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed.
|
|
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed.
|
|
break;
|
|
break;
|
|
for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootWindow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow)
|
|
for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootWindow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow)
|
|
@@ -6912,22 +6920,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
want_focus = true;
|
|
want_focus = true;
|
|
else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
|
|
else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
|
|
want_focus = true;
|
|
want_focus = true;
|
|
-
|
|
|
|
- ImGuiWindow* modal = GetTopMostPopupModal();
|
|
|
|
- if (modal != NULL && !IsWindowWithinBeginStackOf(window, modal))
|
|
|
|
- {
|
|
|
|
- // Avoid focusing a window that is created outside of active modal. This will prevent active modal from being closed.
|
|
|
|
- // Since window is not focused it would reappear at the same display position like the last time it was visible.
|
|
|
|
- // In case of completely new windows it would go to the top (over current modal), but input to such window would still be blocked by modal.
|
|
|
|
- // Position window behind a modal that is not a begin-parent of this window.
|
|
|
|
- want_focus = false;
|
|
|
|
- if (window == window->RootWindow)
|
|
|
|
- {
|
|
|
|
- ImGuiWindow* blocking_modal = FindBlockingModal(window);
|
|
|
|
- IM_ASSERT(blocking_modal != NULL);
|
|
|
|
- BringWindowToDisplayBehind(window, blocking_modal);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// [Test Engine] Register whole window in the item system (before submitting further decorations)
|
|
// [Test Engine] Register whole window in the item system (before submitting further decorations)
|
|
@@ -7140,8 +7132,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
|
|
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
|
|
window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
|
|
window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
|
|
window->DC.NavLayersActiveMaskNext = 0x00;
|
|
window->DC.NavLayersActiveMaskNext = 0x00;
|
|
|
|
+ window->DC.NavIsScrollPushableX = true;
|
|
window->DC.NavHideHighlightOneFrame = false;
|
|
window->DC.NavHideHighlightOneFrame = false;
|
|
- window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
|
|
|
|
|
|
+ window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f);
|
|
|
|
|
|
window->DC.MenuBarAppending = false;
|
|
window->DC.MenuBarAppending = false;
|
|
window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
|
|
window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
|
|
@@ -7164,11 +7157,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
window->AutoFitFramesY--;
|
|
window->AutoFitFramesY--;
|
|
|
|
|
|
// Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
|
|
// Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
|
|
|
|
+ // We ImGuiFocusRequestFlags_UnlessBelowModal to:
|
|
|
|
+ // - Avoid focusing a window that is created outside of a modal. This will prevent active modal from being closed.
|
|
|
|
+ // - Position window behind the modal that is not a begin-parent of this window.
|
|
if (want_focus)
|
|
if (want_focus)
|
|
- {
|
|
|
|
- FocusWindow(window);
|
|
|
|
|
|
+ FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
|
|
|
|
+ if (want_focus && window == g.NavWindow)
|
|
NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls
|
|
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
|
|
// Close requested by platform window
|
|
if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
|
|
if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
|
|
@@ -7456,10 +7451,25 @@ int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
|
|
}
|
|
}
|
|
|
|
|
|
// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
-void ImGui::FocusWindow(ImGuiWindow* window)
|
|
|
|
|
|
+void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
|
|
|
+ // Modal check?
|
|
|
|
+ if (flags & ImGuiFocusRequestFlags_UnlessBelowModal)
|
|
|
|
+ if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
|
|
|
|
+ {
|
|
|
|
+ IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
|
|
|
|
+ if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
|
+ BringWindowToDisplayBehind(window, blocking_modal); // Still bring to right below modal.
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Find last focused child (if any) and focus it instead.
|
|
|
|
+ if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
|
|
|
|
+ window = NavRestoreLastChildNavWindow(window);
|
|
|
|
+
|
|
|
|
+ // Apply focus
|
|
if (g.NavWindow != window)
|
|
if (g.NavWindow != window)
|
|
{
|
|
{
|
|
SetNavWindow(window);
|
|
SetNavWindow(window);
|
|
@@ -7504,7 +7514,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
|
BringWindowToDisplayFront(display_front_window);
|
|
BringWindowToDisplayFront(display_front_window);
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport)
|
|
|
|
|
|
+void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
int start_idx = g.WindowsFocusOrder.Size - 1;
|
|
int start_idx = g.WindowsFocusOrder.Size - 1;
|
|
@@ -7530,16 +7540,16 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
|
|
continue;
|
|
continue;
|
|
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
{
|
|
{
|
|
- // FIXME-DOCK: This is failing (lagging by one frame) for docked windows.
|
|
|
|
|
|
+ // FIXME-DOCK: When ImGuiFocusRequestFlags_RestoreFocusedChild is set...
|
|
|
|
+ // This is failing (lagging by one frame) for docked windows.
|
|
// If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B.
|
|
// If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B.
|
|
// We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update)
|
|
// We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update)
|
|
// to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself?
|
|
// to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself?
|
|
- ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
|
|
|
|
- FocusWindow(focus_window);
|
|
|
|
|
|
+ FocusWindow(window, flags);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- FocusWindow(NULL);
|
|
|
|
|
|
+ FocusWindow(NULL, flags);
|
|
}
|
|
}
|
|
|
|
|
|
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
|
|
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
|
|
@@ -10020,6 +10030,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
DebugLocateItemResolveWithLastItem();
|
|
DebugLocateItemResolveWithLastItem();
|
|
#endif
|
|
#endif
|
|
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
|
|
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
|
|
|
|
+ //if ((g.LastItemData.InFlags & ImGuiItemFlags_NoNav) == 0)
|
|
|
|
+ // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
|
|
|
|
|
|
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
|
|
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
|
|
if (is_rect_visible)
|
|
if (is_rect_visible)
|
|
@@ -10744,6 +10756,7 @@ bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags)
|
|
return IsPopupOpen(id, popup_flags);
|
|
return IsPopupOpen(id, popup_flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Also see FindBlockingModal(NULL)
|
|
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
|
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -10754,6 +10767,7 @@ ImGuiWindow* ImGui::GetTopMostPopupModal()
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// See Demo->Stacked Modal to confirm what this is for.
|
|
ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
|
|
ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -10883,7 +10897,7 @@ void ImGui::ClosePopupsExceptModals()
|
|
for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
|
|
for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
|
|
{
|
|
{
|
|
ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
|
|
ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
|
|
- if (!window || window->Flags & ImGuiWindowFlags_Modal)
|
|
|
|
|
|
+ if (!window || (window->Flags & ImGuiWindowFlags_Modal))
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
|
|
if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
|
|
@@ -10905,16 +10919,9 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
|
|
{
|
|
{
|
|
ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : popup_backup_nav_window;
|
|
ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : popup_backup_nav_window;
|
|
if (focus_window && !focus_window->WasActive && popup_window)
|
|
if (focus_window && !focus_window->WasActive && popup_window)
|
|
- {
|
|
|
|
- // Fallback
|
|
|
|
- FocusTopMostWindowUnderOne(popup_window, NULL, NULL);
|
|
|
|
- }
|
|
|
|
|
|
+ FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild); // Fallback
|
|
else
|
|
else
|
|
- {
|
|
|
|
- if (g.NavLayer == ImGuiNavLayer_Main && focus_window)
|
|
|
|
- focus_window = NavRestoreLastChildNavWindow(focus_window);
|
|
|
|
- FocusWindow(focus_window);
|
|
|
|
- }
|
|
|
|
|
|
+ FocusWindow(focus_window, (g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -11314,12 +11321,12 @@ ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
|
|
return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
|
|
return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
|
|
}
|
|
}
|
|
|
|
|
|
-static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
|
|
|
|
|
|
+static float inline NavScoreItemDistInterval(float cand_min, float cand_max, float curr_min, float curr_max)
|
|
{
|
|
{
|
|
- if (a1 < b0)
|
|
|
|
- return a1 - b0;
|
|
|
|
- if (b1 < a0)
|
|
|
|
- return a0 - b1;
|
|
|
|
|
|
+ if (cand_max < curr_min)
|
|
|
|
+ return cand_max - curr_min;
|
|
|
|
+ if (curr_max < cand_min)
|
|
|
|
+ return cand_min - curr_max;
|
|
return 0.0f;
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -11401,11 +11408,12 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
|
|
quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
|
|
quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const ImGuiDir move_dir = g.NavMoveDir;
|
|
#if IMGUI_DEBUG_NAV_SCORING
|
|
#if IMGUI_DEBUG_NAV_SCORING
|
|
char buf[200];
|
|
char buf[200];
|
|
if (g.IO.KeyCtrl) // Hold CTRL to preview score in matching quadrant. CTRL+Arrow to rotate.
|
|
if (g.IO.KeyCtrl) // Hold CTRL to preview score in matching quadrant. CTRL+Arrow to rotate.
|
|
{
|
|
{
|
|
- if (quadrant == g.NavMoveDir)
|
|
|
|
|
|
+ if (quadrant == move_dir)
|
|
{
|
|
{
|
|
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
|
|
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
|
|
ImDrawList* draw_list = GetForegroundDrawList(window);
|
|
ImDrawList* draw_list = GetForegroundDrawList(window);
|
|
@@ -11429,7 +11437,6 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
|
|
|
|
|
|
// Is it in the quadrant we're interested in moving to?
|
|
// Is it in the quadrant we're interested in moving to?
|
|
bool new_best = false;
|
|
bool new_best = false;
|
|
- const ImGuiDir move_dir = g.NavMoveDir;
|
|
|
|
if (quadrant == move_dir)
|
|
if (quadrant == move_dir)
|
|
{
|
|
{
|
|
// Does it beat the current best candidate?
|
|
// Does it beat the current best candidate?
|
|
@@ -11485,6 +11492,15 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
|
|
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
|
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// True when current work location may be scrolled horizontally when moving left / right.
|
|
|
|
+// This is generally always true UNLESS within a column. We don't have a vertical equivalent.
|
|
|
|
+void ImGui::NavUpdateCurrentWindowIsScrollPushableX()
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
+ window->DC.NavIsScrollPushableX = (g.CurrentTable == NULL && window->DC.CurrentColumns == NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
|
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
|
// This is called after LastItemData is set.
|
|
// This is called after LastItemData is set.
|
|
static void ImGui::NavProcessItem()
|
|
static void ImGui::NavProcessItem()
|
|
@@ -11492,9 +11508,16 @@ static void ImGui::NavProcessItem()
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
const ImGuiID id = g.LastItemData.ID;
|
|
const ImGuiID id = g.LastItemData.ID;
|
|
- const ImRect nav_bb = g.LastItemData.NavRect;
|
|
|
|
const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
|
|
const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
|
|
|
|
|
|
|
|
+ // When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221)
|
|
|
|
+ if (window->DC.NavIsScrollPushableX == false)
|
|
|
|
+ {
|
|
|
|
+ g.LastItemData.NavRect.Min.x = ImClamp(g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
|
|
|
|
+ g.LastItemData.NavRect.Max.x = ImClamp(g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
|
|
|
|
+ }
|
|
|
|
+ const ImRect nav_bb = g.LastItemData.NavRect;
|
|
|
|
+
|
|
// Process Init Request
|
|
// Process Init Request
|
|
if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
|
|
if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
|
|
{
|
|
{
|
|
@@ -11536,7 +11559,7 @@ static void ImGui::NavProcessItem()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Update window-relative bounding box of navigated item
|
|
|
|
|
|
+ // Update information for currently focused/navigated item
|
|
if (g.NavId == id)
|
|
if (g.NavId == id)
|
|
{
|
|
{
|
|
if (g.NavWindow != window)
|
|
if (g.NavWindow != window)
|
|
@@ -11544,7 +11567,7 @@ static void ImGui::NavProcessItem()
|
|
g.NavLayer = window->DC.NavLayerCurrent;
|
|
g.NavLayer = window->DC.NavLayerCurrent;
|
|
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
|
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
|
g.NavIdIsAlive = true;
|
|
g.NavIdIsAlive = true;
|
|
- window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position)
|
|
|
|
|
|
+ window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -11938,7 +11961,7 @@ static void ImGui::NavUpdate()
|
|
ImGuiWindow* window = g.NavWindow;
|
|
ImGuiWindow* window = g.NavWindow;
|
|
const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
|
const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
|
const ImGuiDir move_dir = g.NavMoveDir;
|
|
const ImGuiDir move_dir = g.NavMoveDir;
|
|
- if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && move_dir != ImGuiDir_None)
|
|
|
|
|
|
+ if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None)
|
|
{
|
|
{
|
|
if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
|
|
if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
|
|
SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
|
|
SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
|
|
@@ -12056,6 +12079,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
|
{
|
|
{
|
|
if (g.NavMoveDir == ImGuiDir_None)
|
|
if (g.NavMoveDir == ImGuiDir_None)
|
|
g.NavMoveDir = g.NavMoveDirForDebug;
|
|
g.NavMoveDir = g.NavMoveDirForDebug;
|
|
|
|
+ g.NavMoveClipDir = g.NavMoveDir;
|
|
g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
|
|
g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -12169,6 +12193,7 @@ void ImGui::NavMoveRequestApplyResult()
|
|
g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
|
|
g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
|
|
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
|
|
if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
|
|
NavRestoreHighlightAfterMove();
|
|
NavRestoreHighlightAfterMove();
|
|
|
|
+ IMGUI_DEBUG_LOG_NAV("[nav] NavMoveSubmitted but not led to a result!\n");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -12305,7 +12330,7 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|
if (g.NavLayer != ImGuiNavLayer_Main)
|
|
if (g.NavLayer != ImGuiNavLayer_Main)
|
|
NavRestoreLayer(ImGuiNavLayer_Main);
|
|
NavRestoreLayer(ImGuiNavLayer_Main);
|
|
|
|
|
|
- if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll)
|
|
|
|
|
|
+ if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY)
|
|
{
|
|
{
|
|
// Fallback manual-scroll when window has no navigable item
|
|
// Fallback manual-scroll when window has no navigable item
|
|
if (IsKeyPressed(ImGuiKey_PageUp, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat))
|
|
if (IsKeyPressed(ImGuiKey_PageUp, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat))
|
|
@@ -12483,7 +12508,7 @@ static void ImGui::NavUpdateWindowing()
|
|
bool apply_toggle_layer = false;
|
|
bool apply_toggle_layer = false;
|
|
|
|
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
- bool allow_windowing = (modal_window == NULL);
|
|
|
|
|
|
+ bool allow_windowing = (modal_window == NULL); // FIXME: This prevent CTRL+TAB from being usable with windows over a popup
|
|
if (!allow_windowing)
|
|
if (!allow_windowing)
|
|
g.NavWindowingTarget = NULL;
|
|
g.NavWindowingTarget = NULL;
|
|
|
|
|
|
@@ -12615,9 +12640,9 @@ static void ImGui::NavUpdateWindowing()
|
|
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
|
|
ImGuiViewport* previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
|
|
ClearActiveID();
|
|
ClearActiveID();
|
|
NavRestoreHighlightAfterMove();
|
|
NavRestoreHighlightAfterMove();
|
|
- apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
|
|
|
|
ClosePopupsOverWindow(apply_focus_window, false);
|
|
ClosePopupsOverWindow(apply_focus_window, false);
|
|
- FocusWindow(apply_focus_window);
|
|
|
|
|
|
+ FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
|
|
|
|
+ apply_focus_window = g.NavWindow;
|
|
if (apply_focus_window->NavLastIds[0] == 0)
|
|
if (apply_focus_window->NavLastIds[0] == 0)
|
|
NavInitWindow(apply_focus_window, false);
|
|
NavInitWindow(apply_focus_window, false);
|
|
|
|
|
|
@@ -13935,7 +13960,7 @@ static void ImGui::UpdateViewportsNewFrame()
|
|
if (focused_viewport->Window != NULL)
|
|
if (focused_viewport->Window != NULL)
|
|
FocusWindow(NavRestoreLastChildNavWindow(focused_viewport->Window));
|
|
FocusWindow(NavRestoreLastChildNavWindow(focused_viewport->Window));
|
|
else if (focused_viewport->LastFocusedHadNavWindow)
|
|
else if (focused_viewport->LastFocusedHadNavWindow)
|
|
- FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport);
|
|
|
|
|
|
+ FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport, ImGuiFocusRequestFlags_None);
|
|
else
|
|
else
|
|
FocusWindow(NULL);
|
|
FocusWindow(NULL);
|
|
}
|
|
}
|
|
@@ -20127,7 +20152,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
|
TextUnformatted(line_begin, line_end);
|
|
TextUnformatted(line_begin, line_end);
|
|
ImRect text_rect = g.LastItemData.Rect;
|
|
ImRect text_rect = g.LastItemData.Rect;
|
|
if (IsItemHovered())
|
|
if (IsItemHovered())
|
|
- for (const char* p = line_begin; p < line_end - 10; p++)
|
|
|
|
|
|
+ for (const char* p = line_begin; p <= line_end - 10; p++)
|
|
{
|
|
{
|
|
ImGuiID id = 0;
|
|
ImGuiID id = 0;
|
|
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
|
|
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
|