Skip to content

Commit ab9ce2a

Browse files
committed
Nav: added io.ConfigNavCursorVisibleAuto, io.ConfigNavCursorVisibleAlways. (#1074, #2048, #7237, #8059, #3200, #787)
Note: the NavCursorHideFrames addition is to support 88a3545 even though ConfigNavCursorVisibleAlways is set.
1 parent 3982cb3 commit ab9ce2a

7 files changed

+55
-24
lines changed

docs/CHANGELOG.txt

+20-14
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,26 @@ Other changes:
6969
state to draw callbacks. (#6969, #5834, #7468, #3590)
7070
- IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
7171
- Error Handling: turned a few more functions into recoverable errors. (#1651)
72-
- Nav: added NavSetCursorVisible(bool visible) to manipulate visibility of keyboard/gamepad
73-
navigation cursor. (#1074, #2048, #7237, #8059)
74-
- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
75-
how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
76-
- Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
77-
- Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
78-
- Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
79-
is for some reason your app relies on imgui focus to take other decisions.
80-
- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing
81-
back into same window later.
82-
- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
83-
window. (#3200)
84-
- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
85-
when e.g activating the item with mouse, then Ctrl+Tabbing back and forth.
72+
- Nav (Keyboard/Gamepad navigation):
73+
- Nav: added io.ConfigNavCursorVisibleAuto and io.ConfigNavCursorVisibleAlways to configure
74+
visibility of navigation cursor. (#1074, #2048, #7237, #8059, #3200, #787)
75+
- Set io.ConfigNavCursorVisibleAuto = true (default) to enable automatic toggling
76+
of cursor visibility (mouse click hide the cursor, arrow keys makes it visible).
77+
- Set io.ConfigNavCursorVisibleAlways to keep cursor always visible.
78+
- Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of
79+
navigation cursor (e.g. set default state, or after some actions). (#1074, #2048, #7237, #8059)
80+
- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
81+
how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
82+
- Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
83+
- Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
84+
- Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
85+
is for some reason your app relies on imgui focus to take other decisions.
86+
- Nav: pressing escape to hide nav highlight doesn't clear location from when Ctrl+Tabbing
87+
back into same window later.
88+
- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
89+
window. (#3200)
90+
- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
91+
when e.g activating the item with mouse, then Ctrl+Tabbing back and forth.
8692
- Disabled: clicking a disabled item focuses parent window. (#8064)
8793
- InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
8894
not display navigation highlight. Properly navigation on it by default. (#8057)

docs/TODO.txt

-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
274274
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16-bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
275275

276276
- nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
277-
! nav: never clear NavId on some setup (e.g. gamepad centric)
278277
- nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
279278
- nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
280279
- nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().

imgui.cpp

+17-4
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,8 @@ ImGuiIO::ImGuiIO()
14061406
ConfigNavCaptureKeyboard = true;
14071407
ConfigNavEscapeClearFocusItem = true;
14081408
ConfigNavEscapeClearFocusWindow = false;
1409+
ConfigNavCursorVisibleAuto = true;
1410+
ConfigNavCursorVisibleAlways = false;
14091411

14101412
// Miscellaneous options
14111413
MouseDrawCursor = false;
@@ -3916,6 +3918,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
39163918
NavHighlightActivatedTimer = 0.0f;
39173919
NavInputSource = ImGuiInputSource_Keyboard;
39183920
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
3921+
NavCursorHideFrames = 0;
39193922

39203923
NavAnyRequest = false;
39213924
NavInitRequest = false;
@@ -4828,7 +4831,8 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
48284831
ImGuiContext& g = *GImGui;
48294832
FocusWindow(window);
48304833
SetActiveID(window->MoveId, window);
4831-
g.NavCursorVisible = false;
4834+
if (g.IO.ConfigNavCursorVisibleAuto)
4835+
g.NavCursorVisible = false;
48324836
g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
48334837
g.ActiveIdNoClearOnFocusLoss = true;
48344838
SetActiveIdUsingAllKeyboardKeys();
@@ -12216,14 +12220,17 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
1221612220
void ImGui::SetNavCursorVisible(bool visible)
1221712221
{
1221812222
ImGuiContext& g = *GImGui;
12223+
if (g.IO.ConfigNavCursorVisibleAlways)
12224+
visible = true;
1221912225
g.NavCursorVisible = visible;
1222012226
}
1222112227

1222212228
// (was called NavRestoreHighlightAfterMove() before 1.91.4)
1222312229
void ImGui::SetNavCursorVisibleAfterMove()
1222412230
{
1222512231
ImGuiContext& g = *GImGui;
12226-
g.NavCursorVisible = true;
12232+
if (g.IO.ConfigNavCursorVisibleAuto)
12233+
g.NavCursorVisible = true;
1222712234
g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
1222812235
}
1222912236

@@ -12289,7 +12296,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
1228912296

1229012297
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
1229112298
g.NavHighlightItemUnderNav = true;
12292-
else
12299+
else if (g.IO.ConfigNavCursorVisibleAuto)
1229312300
g.NavCursorVisible = false;
1229412301

1229512302
// Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it)
@@ -12904,6 +12911,9 @@ static void ImGui::NavUpdate()
1290412911
NavMoveRequestApplyResult();
1290512912
g.NavTabbingCounter = 0;
1290612913
g.NavMoveSubmitted = g.NavMoveScoringItems = false;
12914+
if (g.NavCursorHideFrames > 0)
12915+
if (--g.NavCursorHideFrames == 0)
12916+
g.NavCursorVisible = true;
1290712917

1290812918
// Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
1290912919
bool set_mouse_pos = false;
@@ -12958,6 +12968,8 @@ static void ImGui::NavUpdate()
1295812968
}
1295912969
if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
1296012970
g.NavCursorVisible = false;
12971+
else if (g.IO.ConfigNavCursorVisibleAlways && g.NavCursorHideFrames == 0)
12972+
g.NavCursorVisible = true;
1296112973
if (g.NavActivateId != 0)
1296212974
IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
1296312975

@@ -13158,7 +13170,8 @@ void ImGui::NavUpdateCreateMoveRequest()
1315813170
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "<NULL>", g.NavLayer);
1315913171
g.NavInitRequest = g.NavInitRequestFromMove = true;
1316013172
g.NavInitResult.ID = 0;
13161-
g.NavCursorVisible = true;
13173+
if (g.IO.ConfigNavCursorVisibleAuto)
13174+
g.NavCursorVisible = true;
1316213175
}
1316313176

1316413177
// When using gamepad, we project the reference nav bounding box into window visible area.

imgui.h

+2
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,8 @@ struct ImGuiIO
22522252
bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set.
22532253
bool ConfigNavEscapeClearFocusItem; // = true // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
22542254
bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
2255+
bool ConfigNavCursorVisibleAuto; // = true // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
2256+
bool ConfigNavCursorVisibleAlways; // = false // Navigation cursor is always visible.
22552257

22562258
// Miscellaneous options
22572259
// (you can visualize and interact with all options in 'Demo->Configuration')

imgui_demo.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
527527
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
528528
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
529529

530-
ImGui::SeparatorText("Navigation");
530+
ImGui::SeparatorText("Keyboard/Gamepad Navigation");
531531
ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
532532
ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
533533
ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
@@ -536,6 +536,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
536536
ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item.");
537537
ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
538538
ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
539+
ImGui::Checkbox("io.ConfigNavCursorVisibleAuto", &io.ConfigNavCursorVisibleAuto);
540+
ImGui::SameLine(); HelpMarker("Using directional navigation key makes the cursor visible. Mouse click hides the cursor.");
541+
ImGui::Checkbox("io.ConfigNavCursorVisibleAlways", &io.ConfigNavCursorVisibleAlways);
542+
ImGui::SameLine(); HelpMarker("Navigation cursor is always visible.");
539543

540544
ImGui::SeparatorText("Widgets");
541545
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);

imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,7 @@ struct ImGuiContext
21542154
ImGuiActivateFlags NavNextActivateFlags;
21552155
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
21562156
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
2157+
ImS8 NavCursorHideFrames;
21572158

21582159
// Navigation: Init & Move Requests
21592160
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()

imgui_widgets.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
619619
pressed = true;
620620
}
621621

622-
if (pressed)
622+
if (pressed && g.IO.ConfigNavCursorVisibleAuto)
623623
g.NavCursorVisible = false;
624624
}
625625

@@ -688,7 +688,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
688688
}
689689
ClearActiveID();
690690
}
691-
if (!(flags & ImGuiButtonFlags_NoNavFocus))
691+
if (!(flags & ImGuiButtonFlags_NoNavFocus) && g.IO.ConfigNavCursorVisibleAuto)
692692
g.NavCursorVisible = false;
693693
}
694694
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
@@ -7001,7 +7001,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
70017001
if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
70027002
{
70037003
SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
7004-
g.NavCursorVisible = false;
7004+
if (g.IO.ConfigNavCursorVisibleAuto)
7005+
g.NavCursorVisible = false;
70057006
}
70067007
}
70077008
if (pressed)
@@ -8624,7 +8625,12 @@ void ImGui::EndMenuBar()
86248625
IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary)
86258626
FocusWindow(window);
86268627
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
8627-
g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection.
8628+
// FIXME-NAV: How to deal with this when not using g.IO.ConfigNavCursorVisibleAuto?
8629+
if (g.NavCursorVisible)
8630+
{
8631+
g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection. Will be set again
8632+
g.NavCursorHideFrames = 2;
8633+
}
86288634
g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
86298635
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
86308636
}

0 commit comments

Comments
 (0)