mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 01:17:00 +00:00
Nav, Menus: Fix vertical wrap-around in menus or popups created with multiple appending calls to BeginMenu()/EndMenu() or BeginPopup/EndPopup(). (#3223, #1207)
First call to EndPopup() called NavRequestTryWrapWindow() which performed wrap-around operation while we were not done composing menu. This resulted in navigation wrapping around to first item. Since wrap-around operation is only valid in last call to EndPopup() and there is no way to know which call is last - this operation is delayed to the end of the frame.
This commit is contained in:
parent
7b3d379819
commit
a6f4b0fd70
@ -51,6 +51,8 @@ Other Changes:
|
|||||||
Set to FLT_MAX to only display a close button when selected (merely hovering is not enough).
|
Set to FLT_MAX to only display a close button when selected (merely hovering is not enough).
|
||||||
Set to an intermediary value to toggle behavior based on width (same as Firefox).
|
Set to an intermediary value to toggle behavior based on width (same as Firefox).
|
||||||
- Metrics: Added a "Settings" section with some details about persistent ini settings.
|
- Metrics: Added a "Settings" section with some details about persistent ini settings.
|
||||||
|
- Nav, Menus: Fix vertical wrap-around in menus or popups created with multiple appending calls to
|
||||||
|
BeginMenu()/EndMenu() or BeginPopup/EndPopup(). (#3223, #1207) [@rokups]
|
||||||
- Backends: Win32: Support for #define NOGDI, won't try to call GetDeviceCaps(). (#3137, #2327)
|
- Backends: Win32: Support for #define NOGDI, won't try to call GetDeviceCaps(). (#3137, #2327)
|
||||||
- Backends: Win32: Fix _WIN32_WINNT < 0x0600 (MinGW defaults to 0x502 == Windows 2003). (#3183)
|
- Backends: Win32: Fix _WIN32_WINNT < 0x0600 (MinGW defaults to 0x502 == Windows 2003). (#3183)
|
||||||
- Backends: OpenGL: Fixed handling of GL 4.5+ glClipControl(GL_UPPER_LEFT) by inverting the
|
- Backends: OpenGL: Fixed handling of GL 4.5+ glClipControl(GL_UPPER_LEFT) by inverting the
|
||||||
|
104
imgui.cpp
104
imgui.cpp
@ -937,6 +937,7 @@ static void NavUpdateWindowingOverlay();
|
|||||||
static void NavUpdateMoveResult();
|
static void NavUpdateMoveResult();
|
||||||
static float NavUpdatePageUpPageDown();
|
static float NavUpdatePageUpPageDown();
|
||||||
static inline void NavUpdateAnyRequestFlag();
|
static inline void NavUpdateAnyRequestFlag();
|
||||||
|
static void NavEndFrame();
|
||||||
static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand);
|
static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand);
|
||||||
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
|
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
|
||||||
static ImVec2 NavCalcPreferredRefPos();
|
static ImVec2 NavCalcPreferredRefPos();
|
||||||
@ -4209,9 +4210,8 @@ void ImGui::EndFrame()
|
|||||||
g.CurrentWindow->Active = false;
|
g.CurrentWindow->Active = false;
|
||||||
End();
|
End();
|
||||||
|
|
||||||
// Show CTRL+TAB list window
|
// Update navigation: CTRL+Tab, wrap-around requests
|
||||||
if (g.NavWindowingTarget != NULL)
|
NavEndFrame();
|
||||||
NavUpdateWindowingOverlay();
|
|
||||||
|
|
||||||
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
|
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
|
||||||
if (g.DragDropActive)
|
if (g.DragDropActive)
|
||||||
@ -7819,6 +7819,7 @@ void ImGui::EndPopup()
|
|||||||
IM_ASSERT(g.BeginPopupStack.Size > 0);
|
IM_ASSERT(g.BeginPopupStack.Size > 0);
|
||||||
|
|
||||||
// Make all menus and popups wrap around for now, may need to expose that policy.
|
// Make all menus and popups wrap around for now, may need to expose that policy.
|
||||||
|
if (g.NavWindow == window)
|
||||||
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
|
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
|
||||||
|
|
||||||
// Child-popups don't need to be laid out
|
// Child-popups don't need to be laid out
|
||||||
@ -8298,36 +8299,11 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im
|
|||||||
void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
|
void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != ImGuiNavLayer_Main)
|
|
||||||
return;
|
|
||||||
IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
|
|
||||||
ImRect bb_rel = window->NavRectRel[0];
|
|
||||||
|
|
||||||
ImGuiDir clip_dir = g.NavMoveDir;
|
// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
|
||||||
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
// popup is assembled and in case of appended popups it is not clear which EndPopup() call is final.
|
||||||
{
|
g.NavWrapRequestWindow = window;
|
||||||
bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x;
|
g.NavWrapRequestFlags = move_flags;
|
||||||
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
|
|
||||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
|
||||||
}
|
|
||||||
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
|
||||||
{
|
|
||||||
bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
|
|
||||||
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
|
|
||||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
|
||||||
}
|
|
||||||
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
|
||||||
{
|
|
||||||
bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y;
|
|
||||||
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
|
|
||||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
|
||||||
}
|
|
||||||
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
|
||||||
{
|
|
||||||
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
|
|
||||||
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
|
|
||||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
|
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
|
||||||
@ -8457,6 +8433,8 @@ static void ImGui::NavUpdate()
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.IO.WantSetMousePos = false;
|
g.IO.WantSetMousePos = false;
|
||||||
|
g.NavWrapRequestWindow = NULL;
|
||||||
|
g.NavWrapRequestFlags = ImGuiNavMoveFlags_None;
|
||||||
#if 0
|
#if 0
|
||||||
if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
|
if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
|
||||||
#endif
|
#endif
|
||||||
@ -8870,6 +8848,68 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ImGui::NavEndFrame()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
// Show CTRL+TAB list window
|
||||||
|
if (g.NavWindowingTarget != NULL)
|
||||||
|
NavUpdateWindowingOverlay();
|
||||||
|
|
||||||
|
// Perform wrap-around in menus
|
||||||
|
ImGuiWindow* window = g.NavWrapRequestWindow;
|
||||||
|
ImGuiNavMoveFlags move_flags = g.NavWrapRequestFlags;
|
||||||
|
if (window != NULL && g.NavWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == ImGuiNavLayer_Main)
|
||||||
|
{
|
||||||
|
IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
|
||||||
|
ImRect bb_rel = window->NavRectRel[0];
|
||||||
|
|
||||||
|
ImGuiDir clip_dir = g.NavMoveDir;
|
||||||
|
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||||
|
{
|
||||||
|
bb_rel.Min.x = bb_rel.Max.x =
|
||||||
|
ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x;
|
||||||
|
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
||||||
|
{
|
||||||
|
bb_rel.TranslateY(-bb_rel.GetHeight());
|
||||||
|
clip_dir = ImGuiDir_Up;
|
||||||
|
}
|
||||||
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||||
|
}
|
||||||
|
if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||||
|
{
|
||||||
|
bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
|
||||||
|
if (move_flags & ImGuiNavMoveFlags_WrapX)
|
||||||
|
{
|
||||||
|
bb_rel.TranslateY(+bb_rel.GetHeight());
|
||||||
|
clip_dir = ImGuiDir_Down;
|
||||||
|
}
|
||||||
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||||
|
}
|
||||||
|
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||||
|
{
|
||||||
|
bb_rel.Min.y = bb_rel.Max.y =
|
||||||
|
ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y;
|
||||||
|
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||||
|
{
|
||||||
|
bb_rel.TranslateX(-bb_rel.GetWidth());
|
||||||
|
clip_dir = ImGuiDir_Left;
|
||||||
|
}
|
||||||
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||||
|
}
|
||||||
|
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||||
|
{
|
||||||
|
bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
|
||||||
|
if (move_flags & ImGuiNavMoveFlags_WrapY)
|
||||||
|
{
|
||||||
|
bb_rel.TranslateX(+bb_rel.GetWidth());
|
||||||
|
clip_dir = ImGuiDir_Right;
|
||||||
|
}
|
||||||
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
|
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
@ -1207,6 +1207,8 @@ struct ImGuiContext
|
|||||||
ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow
|
ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow
|
||||||
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
||||||
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
||||||
|
ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around.
|
||||||
|
ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags.
|
||||||
|
|
||||||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
||||||
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
||||||
@ -1383,6 +1385,8 @@ struct ImGuiContext
|
|||||||
NavMoveRequestForward = ImGuiNavForward_None;
|
NavMoveRequestForward = ImGuiNavForward_None;
|
||||||
NavMoveRequestKeyMods = ImGuiKeyModFlags_None;
|
NavMoveRequestKeyMods = ImGuiKeyModFlags_None;
|
||||||
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
||||||
|
NavWrapRequestWindow = NULL;
|
||||||
|
NavWrapRequestFlags = ImGuiNavMoveFlags_None;
|
||||||
|
|
||||||
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
|
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
|
||||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||||
|
Loading…
Reference in New Issue
Block a user