Focus: start moving modal check into FocusWindow(), add ImGuiFocusRequestFlags_UnlessBelowModal (currently opt-in, should try to make opt-out). (#6357, #4317)
This commit is contained in:
parent
f0fe1957a8
commit
30eceaf95f
33
imgui.cpp
33
imgui.cpp
@ -1056,7 +1056,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
|
||||||
static void UpdateViewportsNewFrame();
|
static void UpdateViewportsNewFrame();
|
||||||
@ -3911,7 +3910,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;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -4296,10 +4295,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4624,7 +4623,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_None);
|
||||||
|
|
||||||
// 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.
|
||||||
@ -6077,7 +6076,7 @@ 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)
|
ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.OpenPopupStack.Size <= 0)
|
if (g.OpenPopupStack.Size <= 0)
|
||||||
@ -6091,6 +6090,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)
|
||||||
@ -6928,10 +6929,19 @@ 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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply focus
|
||||||
if (g.NavWindow != window)
|
if (g.NavWindow != window)
|
||||||
{
|
{
|
||||||
SetNavWindow(window);
|
SetNavWindow(window);
|
||||||
@ -6968,7 +6978,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;
|
||||||
IM_UNUSED(filter_viewport); // Unused in master branch.
|
IM_UNUSED(filter_viewport); // Unused in master branch.
|
||||||
@ -6994,11 +7004,11 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
|
|||||||
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
||||||
{
|
{
|
||||||
ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
|
ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
|
||||||
FocusWindow(focus_window);
|
FocusWindow(focus_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.
|
||||||
@ -10101,6 +10111,7 @@ bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags)
|
|||||||
return IsPopupOpen(id, popup_flags);
|
return IsPopupOpen(id, popup_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: In principle we should converge toward replacing calls to GetTopMostPopupModal() + IsWindowWithinBeginStackOf() with calls to FindBlockingModal()
|
||||||
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -10263,7 +10274,7 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
|
|||||||
if (focus_window && !focus_window->WasActive && popup_window)
|
if (focus_window && !focus_window->WasActive && popup_window)
|
||||||
{
|
{
|
||||||
// Fallback
|
// Fallback
|
||||||
FocusTopMostWindowUnderOne(popup_window, NULL, NULL);
|
FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_None);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -164,6 +164,7 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
|
|||||||
// Flags
|
// Flags
|
||||||
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
|
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
|
||||||
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
|
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
|
||||||
|
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow();
|
||||||
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc.
|
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc.
|
||||||
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
|
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
|
||||||
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
|
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
|
||||||
@ -906,6 +907,15 @@ enum ImGuiSeparatorFlags_
|
|||||||
ImGuiSeparatorFlags_SpanAllColumns = 1 << 2,
|
ImGuiSeparatorFlags_SpanAllColumns = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Flags for FocusWindow(). This is not called ImGuiFocusFlags to avoid confusion with public-facing ImGuiFocusedFlags.
|
||||||
|
// FIXME: Once we finishing replacing more uses of GetTopMostPopupModal()+IsWindowWithinBeginStackOf()
|
||||||
|
// and FindBlockingModal() with this, we may want to change the flag to be opt-out instead of opt-in.
|
||||||
|
enum ImGuiFocusRequestFlags_
|
||||||
|
{
|
||||||
|
ImGuiFocusRequestFlags_None = 0,
|
||||||
|
ImGuiFocusRequestFlags_UnlessBelowModal = 1 << 0, // Do not set focus if the window is below a modal.
|
||||||
|
};
|
||||||
|
|
||||||
enum ImGuiTextFlags_
|
enum ImGuiTextFlags_
|
||||||
{
|
{
|
||||||
ImGuiTextFlags_None = 0,
|
ImGuiTextFlags_None = 0,
|
||||||
@ -2751,8 +2761,8 @@ namespace ImGui
|
|||||||
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
|
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
|
||||||
|
|
||||||
// Windows: Display Order and Focus Order
|
// Windows: Display Order and Focus Order
|
||||||
IMGUI_API void FocusWindow(ImGuiWindow* window);
|
IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0);
|
||||||
IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport);
|
IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags);
|
||||||
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
|
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
|
||||||
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
|
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
|
||||||
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
|
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
|
||||||
@ -2872,6 +2882,7 @@ namespace ImGui
|
|||||||
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
|
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
|
||||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||||
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
|
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
|
||||||
|
IMGUI_API ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
|
||||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||||
|
|
||||||
|
@ -7084,7 +7084,7 @@ void ImGui::EndMainMenuBar()
|
|||||||
// FIXME: With this strategy we won't be able to restore a NULL focus.
|
// FIXME: With this strategy we won't be able to restore a NULL focus.
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
|
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
|
||||||
FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL);
|
FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
|
||||||
|
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user