Skip to content

Commit e99c4fc

Browse files
committed
Nav: fixes keyboard/gamepad nav actions running without the corresponding config flags (ocornut#5504). Fixes 8b8a61b. ocornut#4921, ocornut#4858, ocornut#787, ocornut#1599, ocornut#323)
NavUpdate() can now clears ImGuiInputSource_None.
1 parent 2d38bc9 commit e99c4fc

6 files changed

+39
-27
lines changed

backends/imgui_impl_glfw.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0
582582
static void ImGui_ImplGlfw_UpdateGamepads()
583583
{
584584
ImGuiIO& io = ImGui::GetIO();
585-
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
585+
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
586586
return;
587587

588588
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;

backends/imgui_impl_osx.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static void ImGui_ImplOSX_UpdateGamepads()
517517
{
518518
ImGuiIO& io = ImGui::GetIO();
519519
memset(io.NavInputs, 0, sizeof(io.NavInputs));
520-
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
520+
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
521521
return;
522522

523523
#if APPLE_HAS_CONTROLLER

backends/imgui_impl_sdl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
481481
static void ImGui_ImplSDL2_UpdateGamepads()
482482
{
483483
ImGuiIO& io = ImGui::GetIO();
484-
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
484+
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
485485
return;
486486

487487
// Get gamepad

backends/imgui_impl_win32.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ static void ImGui_ImplWin32_UpdateGamepads()
277277
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
278278
ImGuiIO& io = ImGui::GetIO();
279279
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
280-
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
281-
return;
280+
//if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
281+
// return;
282282

283283
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
284284
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.

imgui.cpp

+31-20
Original file line numberDiff line numberDiff line change
@@ -10266,6 +10266,10 @@ static void ImGui::NavUpdate()
1026610266
for (ImGuiKey key : nav_keyboard_keys_to_change_source)
1026710267
if (IsKeyDown(key))
1026810268
g.NavInputSource = ImGuiInputSource_Keyboard;
10269+
if (!nav_gamepad_active && g.NavInputSource == ImGuiInputSource_Gamepad)
10270+
g.NavInputSource = ImGuiInputSource_None;
10271+
if (!nav_keyboard_active && g.NavInputSource == ImGuiInputSource_Keyboard)
10272+
g.NavInputSource = ImGuiInputSource_None;
1026910273

1027010274
// Process navigation init request (select first/default focus)
1027110275
if (g.NavInitResultId != 0)
@@ -10310,10 +10314,10 @@ static void ImGui::NavUpdate()
1031010314
g.NavActivateFlags = ImGuiActivateFlags_None;
1031110315
if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
1031210316
{
10313-
const bool activate_down = IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_NavGamepadActivate);
10314-
const bool activate_pressed = activate_down && (IsKeyPressed(ImGuiKey_Space, false) || IsKeyPressed(ImGuiKey_NavGamepadActivate, false));
10315-
const bool input_down = IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadInput);
10316-
const bool input_pressed = input_down && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
10317+
const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate));
10318+
const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false)));
10319+
const bool input_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Enter)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput));
10320+
const bool input_pressed = input_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Enter, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false)));
1031710321
if (g.ActiveId == 0 && activate_pressed)
1031810322
{
1031910323
g.NavActivateId = g.NavId;
@@ -10368,14 +10372,17 @@ static void ImGui::NavUpdate()
1036810372
SetScrollY(window, ImFloor(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
1036910373
}
1037010374

10371-
// *Normal* Manual scroll with NavScrollXXX keys
10375+
// *Normal* Manual scroll with LStick
1037210376
// Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
10373-
const ImVec2 scroll_dir = GetKeyVector2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
10374-
const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f;
10375-
if (scroll_dir.x != 0.0f && window->ScrollbarX)
10376-
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
10377-
if (scroll_dir.y != 0.0f)
10378-
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
10377+
if (nav_gamepad_active)
10378+
{
10379+
const ImVec2 scroll_dir = GetKeyVector2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
10380+
const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f;
10381+
if (scroll_dir.x != 0.0f && window->ScrollbarX)
10382+
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
10383+
if (scroll_dir.y != 0.0f)
10384+
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
10385+
}
1037910386
}
1038010387

1038110388
// Always prioritize mouse highlight if navigation is disabled
@@ -10427,6 +10434,8 @@ void ImGui::NavUpdateCreateMoveRequest()
1042710434
ImGuiContext& g = *GImGui;
1042810435
ImGuiIO& io = g.IO;
1042910436
ImGuiWindow* window = g.NavWindow;
10437+
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
10438+
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
1043010439

1043110440
if (g.NavMoveForwardToNextFrame && window != NULL)
1043210441
{
@@ -10445,18 +10454,17 @@ void ImGui::NavUpdateCreateMoveRequest()
1044510454
if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
1044610455
{
1044710456
const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateNavMove;
10448-
if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsKeyPressedEx(ImGuiKey_GamepadDpadLeft, repeat_mode) || IsKeyPressedEx(ImGuiKey_LeftArrow, repeat_mode))) { g.NavMoveDir = ImGuiDir_Left; }
10449-
if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsKeyPressedEx(ImGuiKey_GamepadDpadRight, repeat_mode) || IsKeyPressedEx(ImGuiKey_RightArrow, repeat_mode))) { g.NavMoveDir = ImGuiDir_Right; }
10450-
if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsKeyPressedEx(ImGuiKey_GamepadDpadUp, repeat_mode) || IsKeyPressedEx(ImGuiKey_UpArrow, repeat_mode))) { g.NavMoveDir = ImGuiDir_Up; }
10451-
if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && (IsKeyPressedEx(ImGuiKey_GamepadDpadDown, repeat_mode) || IsKeyPressedEx(ImGuiKey_DownArrow, repeat_mode))) { g.NavMoveDir = ImGuiDir_Down; }
10457+
if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressedEx(ImGuiKey_GamepadDpadLeft, repeat_mode)) || (nav_keyboard_active && IsKeyPressedEx(ImGuiKey_LeftArrow, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Left; }
10458+
if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressedEx(ImGuiKey_GamepadDpadRight, repeat_mode)) || (nav_keyboard_active && IsKeyPressedEx(ImGuiKey_RightArrow, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Right; }
10459+
if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressedEx(ImGuiKey_GamepadDpadUp, repeat_mode)) || (nav_keyboard_active && IsKeyPressedEx(ImGuiKey_UpArrow, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Up; }
10460+
if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && ((nav_gamepad_active && IsKeyPressedEx(ImGuiKey_GamepadDpadDown, repeat_mode)) || (nav_keyboard_active && IsKeyPressedEx(ImGuiKey_DownArrow, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Down; }
1045210461
}
1045310462
g.NavMoveClipDir = g.NavMoveDir;
1045410463
g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
1045510464
}
1045610465

1045710466
// Update PageUp/PageDown/Home/End scroll
1045810467
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
10459-
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
1046010468
float scoring_rect_offset_y = 0.0f;
1046110469
if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
1046210470
scoring_rect_offset_y = NavUpdatePageUpPageDown();
@@ -10654,7 +10662,9 @@ void ImGui::NavMoveRequestApplyResult()
1065410662
static void ImGui::NavUpdateCancelRequest()
1065510663
{
1065610664
ImGuiContext& g = *GImGui;
10657-
if (!IsKeyPressed(ImGuiKey_Escape, false) && !IsKeyPressed(ImGuiKey_NavGamepadCancel, false))
10665+
const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
10666+
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
10667+
if (!(nav_keyboard_active && IsKeyPressed(ImGuiKey_Escape, false)) && !(nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, false)))
1065810668
return;
1065910669

1066010670
IMGUI_DEBUG_LOG_NAV("[nav] NavUpdateCancelRequest()\n");
@@ -10906,8 +10916,10 @@ static void ImGui::NavUpdateWindowing()
1090610916
}
1090710917

1090810918
// Start CTRL+Tab or Square+L/R window selection
10909-
const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, false);
10910-
const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressed(ImGuiKey_Tab, false);
10919+
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
10920+
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
10921+
const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, false);
10922+
const bool start_windowing_with_keyboard = allow_windowing && nav_keyboard_active && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressed(ImGuiKey_Tab, false);
1091110923
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
1091210924
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
1091310925
{
@@ -10959,7 +10971,6 @@ static void ImGui::NavUpdateWindowing()
1095910971
// Keyboard: Press and Release ALT to toggle menu layer
1096010972
// - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer.
1096110973
// - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.
10962-
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
1096310974
if (nav_keyboard_active && IsKeyPressed(ImGuiKey_ModAlt))
1096410975
{
1096510976
g.NavWindowingToggleLayer = true;

imgui_widgets.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -4351,9 +4351,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
43514351
const bool is_select_all = is_shortcut_key && IsKeyPressed(ImGuiKey_A);
43524352

43534353
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
4354+
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
43544355
const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true);
4355-
const bool is_gamepad_validate = IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false);
4356-
const bool is_cancel = IsKeyPressed(ImGuiKey_Escape, false) || IsKeyPressed(ImGuiKey_NavGamepadCancel, false);
4356+
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
4357+
const bool is_cancel = IsKeyPressed(ImGuiKey_Escape, false) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, false));
43574358

43584359
if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
43594360
else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }

0 commit comments

Comments
 (0)