Nav, Tabbing: refactor tabbing system to support clipped items, scrolling, using nav queries. (#4449)

Not using counter/modulo anymore and special provisions to handle tab wrapping with ImGuiListClipper. Wrapping may be done better as a next-frame forwarded request.
Also one extra step toward #3949 #3985
This commit is contained in:
ocornut 2021-10-08 15:24:09 +02:00
parent f01a6d3e8f
commit 1a7526dcd4
5 changed files with 138 additions and 152 deletions

View File

@ -44,6 +44,16 @@ Other Changes:
- Added IsMouseTripleClicked() function. Tracking multi-click count in IO structure. (#3229) [@kudaba] - Added IsMouseTripleClicked() function. Tracking multi-click count in IO structure. (#3229) [@kudaba]
- Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527) - Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527)
- Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676) - Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676)
- Nav: tabbing now cycles through clipped items and scroll accordingly. (#4449)
- Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer.
- Nav: fixed resizing window from borders setting navigation to Menu layer.
- Nav: pressing Esc to exit a child window reactivates the Nav highlight if it was disabled by mouse.
- Nav: with ImGuiConfigFlags_NavEnableSetMousePos enabled: Fixed absolute mouse position when using
Home/End leads to scrolling. Fixed not setting mouse position when a failed move request (e.g. when
already at edge) reactivates the navigation highlight.
- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
slightly from the one used by CTRL+arrows. (#2244)
- Clipper: currently focused item is automatically included in clipper range. - Clipper: currently focused item is automatically included in clipper range.
Fixes issue where e.g. drag and dropping an item and scrolling ensure the item source location is Fixes issue where e.g. drag and dropping an item and scrolling ensure the item source location is
still submitted. (#3841, #1725) [@GamingMinds-DanielC, @ocornut] still submitted. (#3841, #1725) [@GamingMinds-DanielC, @ocornut]
@ -51,16 +61,6 @@ Other Changes:
by the clipper to display. (#3841) by the clipper to display. (#3841)
- Clipper: Fixed content height declaration slightly mismatching the value of when not using a clipper. - Clipper: Fixed content height declaration slightly mismatching the value of when not using a clipper.
(an additional ItemSpacing.y was declared, affecting scrollbar range). (an additional ItemSpacing.y was declared, affecting scrollbar range).
- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
- Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer.
- Nav: fixed resizing window from borders setting navigation to Menu layer.
- Nav: pressing Esc to exit a child window reactivates the Nav highlight if it was disabled by mouse.
- Nav: (with ImGuiConfigFlags_NavEnableSetMousePos): fixed absolute mouse position when using Home/End
leads to scrolling.
- Nav: (with ImGuiConfigFlags_NavEnableSetMousePos): fixed not setting mouse position when a failed
move request (e.g. already at edge) reactivate the navigation highlight.
- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
slightly from the one used by CTRL+arrows. (#2244)
- Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce - Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce
likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling
vkCmdSetScissor() explicitly every frame. (#4644) vkCmdSetScissor() explicitly every frame. (#4644)

View File

@ -341,7 +341,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child. - nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..). - nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
- nav: simulate right-click or context activation? (SHIFT+F10) - nav: simulate right-click or context activation? (SHIFT+F10)
- nav/tabbing: refactor old tabbing system and turn into navigation, should pass through all widgets (in submission order?).
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc. - nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) - nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons. - nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.

232
imgui.cpp
View File

@ -916,6 +916,7 @@ static void NavUpdateWindowing();
static void NavUpdateWindowingOverlay(); static void NavUpdateWindowingOverlay();
static void NavUpdateCancelRequest(); static void NavUpdateCancelRequest();
static void NavUpdateCreateMoveRequest(); static void NavUpdateCreateMoveRequest();
static void NavUpdateCreateTabbingRequest();
static float NavUpdatePageUpPageDown(); static float NavUpdatePageUpPageDown();
static inline void NavUpdateAnyRequestFlag(); static inline void NavUpdateAnyRequestFlag();
static void NavUpdateCreateWrappingRequest(); static void NavUpdateCreateWrappingRequest();
@ -923,6 +924,7 @@ static void NavEndFrame();
static bool NavScoreItem(ImGuiNavItemData* result); static bool NavScoreItem(ImGuiNavItemData* result);
static void NavApplyItemToResult(ImGuiNavItemData* result); static void NavApplyItemToResult(ImGuiNavItemData* result);
static void NavProcessItem(); static void NavProcessItem();
static void NavProcessItemForTabbingRequest(ImGuiWindow* window, ImGuiID id);
static ImVec2 NavCalcPreferredRefPos(); static ImVec2 NavCalcPreferredRefPos();
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
@ -940,7 +942,6 @@ static void UpdateDebugToolStackQueries();
static void UpdateSettings(); static void UpdateSettings();
static void UpdateMouseInputs(); static void UpdateMouseInputs();
static void UpdateMouseWheel(); static void UpdateMouseWheel();
static void UpdateTabFocus();
static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect); static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
static void RenderWindowOuterBorders(ImGuiWindow* window); static void RenderWindowOuterBorders(ImGuiWindow* window);
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
@ -2280,9 +2281,11 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items
int end = (int)((rect.Max.y - pos.y) / items_height); int end = (int)((rect.Max.y - pos.y) / items_height);
// When performing a navigation request, ensure we have one item extra in the direction we are moving to // When performing a navigation request, ensure we have one item extra in the direction we are moving to
if (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Up) // FIXME: Verify this works with tabbing
const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up)
start--; start--;
if (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Down) if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down)
end++; end++;
start = ImClamp(start, 0, items_count); start = ImClamp(start, 0, items_count);
@ -2483,8 +2486,11 @@ bool ImGuiListClipper::Step()
else else
{ {
// Add range selected to be included for navigation // Add range selected to be included for navigation
if (g.NavMoveScoringItems) const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
if (is_nav_request)
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0));
if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && g.NavTabbingDir == -1)
data->Ranges.push_back(ImGuiListClipperRange::FromIndices(ItemsCount - 1, ItemsCount));
// Add focused/active item // Add focused/active item
ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]); ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
@ -2492,8 +2498,8 @@ bool ImGuiListClipper::Step()
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
// Add visible range // Add visible range
const int off_min = (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0; const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
const int off_max = (g.NavMoveScoringItems && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0; const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max));
} }
@ -3179,7 +3185,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (id) if (id)
{ {
g.ActiveIdIsAlive = id; g.ActiveIdIsAlive = id;
g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
} }
// Clear declaration of inputs claimed by the widget // Clear declaration of inputs claimed by the widget
@ -3367,48 +3373,6 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
return false; return false;
} }
// Called by ItemAdd()
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
// [WIP] This will eventually be refactored and moved into NavProcessItem()
void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0 && id == g.LastItemData.ID);
// Increment counters
// FIXME: ImGuiItemFlags_Disabled should disable more.
const bool is_tab_stop = (g.LastItemData.InFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
if (is_tab_stop)
{
window->DC.FocusCounterTabStop++;
if (g.NavId == id)
g.NavIdTabCounter = window->DC.FocusCounterTabStop;
}
// 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.TabFocusPressed && g.TabFocusRequestNextWindow == NULL)
{
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.TabFocusRequestCurrWindow == window)
{
if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{
g.NavJustTabbedId = id; // FIXME-NAV: aim to eventually set in NavUpdate() once we finish the refactor
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing;
return;
}
// If another item is about to be focused, we clear our own active id
if (g.ActiveId == id)
ClearActiveID();
}
}
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
{ {
if (wrap_pos_x < 0.0f) if (wrap_pos_x < 0.0f)
@ -3903,44 +3867,6 @@ void ImGui::UpdateMouseWheel()
} }
} }
void ImGui::UpdateTabFocus()
{
ImGuiContext& g = *GImGui;
// Pressing TAB activate widget focus
g.TabFocusPressed = false;
if (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
if (!g.IO.KeyCtrl && !g.IO.KeyAlt && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab))
g.TabFocusPressed = true;
if (g.ActiveId == 0 && g.TabFocusPressed)
{
// - This path is only taken when no widget are active/tabbed-into yet.
// Subsequent tabbing will be processed by FocusableItemRegister()
// - Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields here even though they will be turned into Curr fields below.
g.TabFocusRequestNextWindow = g.NavWindow;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + (g.IO.KeyShift ? -1 : 0);
else
g.TabFocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
}
// Turn queued focus request into current one
g.TabFocusRequestCurrWindow = NULL;
g.TabFocusRequestCurrCounterTabStop = INT_MAX;
if (g.TabFocusRequestNextWindow != NULL)
{
ImGuiWindow* window = g.TabFocusRequestNextWindow;
g.TabFocusRequestCurrWindow = window;
if (g.TabFocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
g.TabFocusRequestCurrCounterTabStop = ImModPositive(g.TabFocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
g.TabFocusRequestNextWindow = NULL;
g.TabFocusRequestNextCounterTabStop = INT_MAX;
}
g.NavIdTabCounter = INT_MAX;
}
// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) // The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
void ImGui::UpdateHoveredWindowAndCaptureFlags() void ImGui::UpdateHoveredWindowAndCaptureFlags()
{ {
@ -4186,9 +4112,6 @@ void ImGui::NewFrame()
// Mouse wheel scrolling, scale // Mouse wheel scrolling, scale
UpdateMouseWheel(); UpdateMouseWheel();
// Update legacy TAB focus
UpdateTabFocus();
// Mark all windows as not visible and compact unused memory. // Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
@ -6399,7 +6322,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.CurrentColumns = NULL; window->DC.CurrentColumns = NULL;
window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.LayoutType = ImGuiLayoutType_Vertical;
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
window->DC.FocusCounterTabStop = -1;
window->DC.ItemWidth = window->ItemWidthDefault; window->DC.ItemWidth = window->ItemWidthDefault;
window->DC.TextWrapPos = -1.0f; // disabled window->DC.TextWrapPos = -1.0f; // disabled
@ -7185,11 +7107,16 @@ void ImGui::SetKeyboardFocusHere(int offset)
IM_ASSERT(offset >= -1); // -1 is allowed but not below IM_ASSERT(offset >= -1); // -1 is allowed but not below
g.NavWindow = window; g.NavWindow = window;
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_None, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_FocusApi, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
if (offset == -1) if (offset == -1)
NavMoveRequestResolveWithLastItem(); {
NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
}
else else
g.NavTabbingInputableRemaining = offset + 1; {
g.NavTabbingDir = 1;
g.NavTabbingCounter = offset + 1;
}
} }
void ImGui::SetItemDefaultFocus() void ImGui::SetItemDefaultFocus()
@ -7671,11 +7598,6 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
return false; return false;
//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]
// [WIP] Tab stop handling (previously was using internal FocusableItemRegister() api)
// FIXME-NAV: We would now want to move this before the clipping test, but this would require being able to scroll and currently this would mean an extra frame. (#4079, #343)
if (extra_flags & ImGuiItemFlags_Inputable)
ItemInputable(window, id);
// 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 (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsMouseHoveringRect(bb.Min, bb.Max))
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
@ -9117,19 +9039,17 @@ static void ImGui::NavProcessItem()
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy)
if (g.NavMoveScoringItems) if (g.NavMoveScoringItems)
{ {
if (item_flags & ImGuiItemFlags_Inputable) const bool is_tab_stop = (item_flags & ImGuiItemFlags_Inputable) && (item_flags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
g.NavTabbingInputableRemaining--; const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) != 0;
if (is_tabbing)
if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav))) {
if (is_tab_stop || (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi))
NavProcessItemForTabbingRequest(window, id);
}
else if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
{ {
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
if (!is_tabbing)
if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
{
if (g.NavTabbingInputableRemaining == 0)
NavMoveRequestResolveWithLastItem();
}
else
{ {
if (NavScoreItem(result)) if (NavScoreItem(result))
NavApplyItemToResult(result); NavApplyItemToResult(result);
@ -9155,6 +9075,52 @@ static void ImGui::NavProcessItem()
} }
} }
// Handle "scoring" of an item for a tabbing/focusing request initiated by NavUpdateCreateTabbingRequest().
// Note that SetKeyboardFocusHere() API calls are considered tabbing requests!
// - Case 1: no nav/active id: set result to first eligible item, stop storing.
// - Case 2: tab forward: on ref id set counter, on counter elapse store result
// - Case 3: tab forward wrap: set result to first eligible item (preemptively), on ref id set counter, on next frame if counter hasn't elapsed store result. // FIXME-TABBING: Could be done as a next-frame forwarded request
// - Case 4: tab backward: store all results, on ref id pick prev, stop storing
// - Case 5: tab backward wrap: store all results, on ref id if no result keep storing until last // FIXME-TABBING: Could be done as next-frame forwarded requested
void ImGui::NavProcessItemForTabbingRequest(ImGuiWindow* window, ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
if (g.NavTabbingDir == +1)
{
// Tab Forward or SetKeyboardFocusHere() with >= 0
if (g.NavTabbingResultFirst.ID == 0)
NavApplyItemToResult(&g.NavTabbingResultFirst);
if (--g.NavTabbingCounter == 0)
NavMoveRequestResolveWithLastItem(result);
else if (g.NavId == id)
g.NavTabbingCounter = 1;
}
else if (g.NavTabbingDir == -1)
{
// Tab Backward
if (g.NavId == id)
{
if (result->ID)
{
g.NavMoveScoringItems = false;
NavUpdateAnyRequestFlag();
}
}
else
{
NavApplyItemToResult(result);
}
}
else if (g.NavTabbingDir == 0)
{
// Tab Init
if (g.NavTabbingResultFirst.ID == 0)
NavMoveRequestResolveWithLastItem(&g.NavTabbingResultFirst);
}
}
bool ImGui::NavMoveRequestButNoResultYet() bool ImGui::NavMoveRequestButNoResultYet()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -9178,18 +9144,18 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM
g.NavMoveScrollFlags = scroll_flags; g.NavMoveScrollFlags = scroll_flags;
g.NavMoveForwardToNextFrame = false; g.NavMoveForwardToNextFrame = false;
g.NavMoveKeyMods = g.IO.KeyMods; g.NavMoveKeyMods = g.IO.KeyMods;
g.NavTabbingInputableRemaining = 0; g.NavTabbingCounter = 0;
g.NavMoveResultLocal.Clear(); g.NavMoveResultLocal.Clear();
g.NavMoveResultLocalVisible.Clear(); g.NavMoveResultLocalVisible.Clear();
g.NavMoveResultOther.Clear(); g.NavMoveResultOther.Clear();
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
} }
void ImGui::NavMoveRequestResolveWithLastItem() void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.NavMoveScoringItems = false; // Ensure request doesn't need more processing g.NavMoveScoringItems = false; // Ensure request doesn't need more processing
NavApplyItemToResult(&g.NavMoveResultLocal); NavApplyItemToResult(result);
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
} }
@ -9424,7 +9390,7 @@ static void ImGui::NavUpdate()
// Process navigation move request // Process navigation move request
if (g.NavMoveSubmitted) if (g.NavMoveSubmitted)
NavMoveRequestApplyResult(); NavMoveRequestApplyResult();
g.NavTabbingInputableRemaining = 0; g.NavTabbingCounter = 0;
g.NavMoveSubmitted = g.NavMoveScoringItems = false; g.NavMoveSubmitted = g.NavMoveScoringItems = false;
// Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling) // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
@ -9433,8 +9399,6 @@ static void ImGui::NavUpdate()
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow) if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
set_mouse_pos = true; set_mouse_pos = true;
g.NavMousePosDirty = false; g.NavMousePosDirty = false;
g.NavIdIsAlive = false;
g.NavJustTabbedId = 0;
IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu); IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
// Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0 // Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0
@ -9496,7 +9460,10 @@ static void ImGui::NavUpdate()
// Process move requests // Process move requests
NavUpdateCreateMoveRequest(); NavUpdateCreateMoveRequest();
if (g.NavMoveDir == ImGuiDir_None)
NavUpdateCreateTabbingRequest();
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
g.NavIdIsAlive = false;
// Scrolling // Scrolling
if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
@ -9668,6 +9635,31 @@ void ImGui::NavUpdateCreateMoveRequest()
g.NavScoringNoClipRect.Add(scoring_rect); g.NavScoringNoClipRect.Add(scoring_rect);
} }
void ImGui::NavUpdateCreateTabbingRequest()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.NavWindow;
IM_ASSERT(g.NavMoveDir == ImGuiDir_None);
if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
return;
const bool tab_pressed = IsKeyPressedMap(ImGuiKey_Tab, true) && !IsActiveIdUsingKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt;
if (!tab_pressed)
return;
// Initiate tabbing request
// (this is ALWAYS ENABLED, regardless of ImGuiConfigFlags_NavEnableKeyboard flag!)
// Initially this was designed to use counters and modulo arithmetic, but that could not work with unsubmitted items (list clipper). Instead we use a strategy close to other move requests.
// See NavProcessItemForTabbingRequest() for a description of the various forward/backward tabbing cases with and without wrapping.
//// FIXME: We use (g.ActiveId == 0) but (g.NavDisableHighlight == false) might be righter once we can tab through anything
g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
NavMoveRequestSubmit(ImGuiDir_None, clip_dir, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
g.NavTabbingResultFirst.Clear();
g.NavTabbingCounter = -1;
}
// Apply result from previous frame navigation directional move request. Always called from NavUpdate() // Apply result from previous frame navigation directional move request. Always called from NavUpdate()
void ImGui::NavMoveRequestApplyResult() void ImGui::NavMoveRequestApplyResult()
{ {
@ -9680,6 +9672,14 @@ void ImGui::NavMoveRequestApplyResult()
// Select which result to use // Select which result to use
ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : (g.NavMoveResultOther.ID != 0) ? &g.NavMoveResultOther : NULL; ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : (g.NavMoveResultOther.ID != 0) ? &g.NavMoveResultOther : NULL;
// Tabbing forward wrap
if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
if (g.NavTabbingCounter == 1 || g.NavTabbingDir == 0)
{
IM_ASSERT(g.NavTabbingResultFirst.ID != 0);
result = &g.NavTabbingResultFirst;
}
// In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result) // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result)
if (result == NULL) if (result == NULL)
{ {

View File

@ -64,7 +64,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.86 WIP" #define IMGUI_VERSION "1.86 WIP"
#define IMGUI_VERSION_NUM 18507 #define IMGUI_VERSION_NUM 18508
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -1247,9 +1247,10 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
ImGuiNavMoveFlags_Forwarded = 1 << 7, ImGuiNavMoveFlags_Forwarded = 1 << 7,
ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result
ImGuiNavMoveFlags_Tabbing = 1 << 9, // == Focus + Activate if item is Inputable + DontChangeNavHighlight ImGuiNavMoveFlags_FocusApi = 1 << 9,
ImGuiNavMoveFlags_Activate = 1 << 10, ImGuiNavMoveFlags_Tabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 11 // Do not alter the visible state of keyboard vs mouse nav highlight ImGuiNavMoveFlags_Activate = 1 << 11,
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 12 // Do not alter the visible state of keyboard vs mouse nav highlight
}; };
enum ImGuiNavLayer enum ImGuiNavLayer
@ -1582,7 +1583,6 @@ struct ImGuiContext
ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0. ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
ImGuiActivateFlags NavActivateFlags; ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustTabbedId; // Just tabbed to this id.
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyModFlags NavJustMovedToKeyMods; ImGuiKeyModFlags NavJustMovedToKeyMods;
@ -1590,7 +1590,6 @@ struct ImGuiContext
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
@ -1614,10 +1613,12 @@ struct ImGuiContext
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted
int NavScoringDebugCount; // Metrics for debugging int NavScoringDebugCount; // Metrics for debugging
int NavTabbingInputableRemaining; // >0 when counting items for tabbing int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id
int NavTabbingCounter; // >0 when counting items for tabbing
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
// 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!
@ -1627,13 +1628,6 @@ struct ImGuiContext
float NavWindowingHighlightAlpha; float NavWindowingHighlightAlpha;
bool NavWindowingToggleLayer; bool NavWindowingToggleLayer;
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!)
ImGuiWindow* TabFocusRequestCurrWindow; //
ImGuiWindow* TabFocusRequestNextWindow; //
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
int TabFocusRequestNextCounterTabStop; // "
bool TabFocusPressed; // Set in NewFrame() when user pressed Tab
// Render // Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
ImGuiMouseCursor MouseCursor; ImGuiMouseCursor MouseCursor;
@ -1800,12 +1794,11 @@ struct ImGuiContext
NavWindow = NULL; NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiKeyModFlags_None; NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
NavInputSource = ImGuiInputSource_None; NavInputSource = ImGuiInputSource_None;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
NavIdTabCounter = INT_MAX;
NavIdIsAlive = false; NavIdIsAlive = false;
NavMousePosDirty = false; NavMousePosDirty = false;
NavDisableHighlight = true; NavDisableHighlight = true;
@ -1822,17 +1815,13 @@ struct ImGuiContext
NavMoveKeyMods = ImGuiKeyModFlags_None; NavMoveKeyMods = ImGuiKeyModFlags_None;
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None; NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
NavScoringDebugCount = 0; NavScoringDebugCount = 0;
NavTabbingInputableRemaining = 0; NavTabbingDir = 0;
NavTabbingCounter = 0;
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false; NavWindowingToggleLayer = false;
TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL;
TabFocusRequestCurrCounterTabStop = INT_MAX;
TabFocusRequestNextCounterTabStop = INT_MAX;
TabFocusPressed = false;
DimBgRatio = 0.0f; DimBgRatio = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow; MouseCursor = ImGuiMouseCursor_Arrow;
@ -1939,7 +1928,6 @@ struct IMGUI_API ImGuiWindowTempData
int CurrentTableIdx; // Current table index (into g.Tables) int CurrentTableIdx; // Current table index (into g.Tables)
ImGuiLayoutType LayoutType; ImGuiLayoutType LayoutType;
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through.
// Local parameters stacks // Local parameters stacks
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
@ -2501,7 +2489,6 @@ namespace ImGui
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API void ItemInputable(ImGuiWindow* window, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
@ -2561,7 +2548,7 @@ namespace ImGui
IMGUI_API bool NavMoveRequestButNoResultYet(); IMGUI_API bool NavMoveRequestButNoResultYet();
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestResolveWithLastItem(); IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);