Nav: clarified/renamed NavInputId as NavAcivateInputId, added flags shared by both.
(this commit should have no visible side effect but is designed to introduce the followup commit refactoring SetKeyboardFocusHere into using a Nav request)
diff --git a/imgui.cpp b/imgui.cpp
index a4e6ed6..0cb5d7d 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3106,7 +3106,7 @@
if (id)
{
g.ActiveIdIsAlive = id;
- g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
+ g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
}
// Clear declaration of inputs claimed by the widget
@@ -7063,6 +7063,7 @@
{
ImGuiContext& g = *GImGui;
g.NavNextActivateId = id;
+ g.NavNextActivateFlags = ImGuiActivateFlags_None;
}
void ImGui::PushFocusScope(ImGuiID id)
@@ -9232,19 +9233,28 @@
NavUpdateCancelRequest();
// Process manual activation request
- g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0;
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavActivateInputId = 0;
+ g.NavActivateFlags = ImGuiActivateFlags_None;
if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
{
bool activate_down = IsNavInputDown(ImGuiNavInput_Activate);
+ bool input_down = IsNavInputDown(ImGuiNavInput_Input);
bool activate_pressed = activate_down && IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed);
+ bool input_pressed = input_down && IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
if (g.ActiveId == 0 && activate_pressed)
+ {
g.NavActivateId = g.NavId;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
+ }
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
+ {
+ g.NavActivateInputId = g.NavId;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
+ }
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
g.NavActivateDownId = g.NavId;
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
g.NavActivatePressedId = g.NavId;
- if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed))
- g.NavInputId = g.NavId;
}
if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
g.NavDisableHighlight = true;
@@ -9254,7 +9264,13 @@
// Process programmatic activation request
// FIXME-NAV: Those should eventually be queued (unlike focus they don't cancel each others)
if (g.NavNextActivateId != 0)
- g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId;
+ {
+ if (g.NavNextActivateFlags & ImGuiActivateFlags_PreferInput)
+ g.NavActivateInputId = g.NavNextActivateId;
+ else
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId;
+ g.NavActivateFlags = g.NavNextActivateFlags;
+ }
g.NavNextActivateId = 0;
// Process move requests
@@ -11393,7 +11409,8 @@
Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
- Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
+ Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId);
+ Text("NavActivateFlags: %04X", g.NavActivateFlags);
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
diff --git a/imgui_internal.h b/imgui_internal.h
index c010a98..c5d7d74 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -143,6 +143,7 @@
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
+typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
@@ -1148,6 +1149,14 @@
// [SECTION] Navigation support
//-----------------------------------------------------------------------------
+enum ImGuiActivateFlags_
+{
+ ImGuiActivateFlags_None = 0,
+ ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default if keyboard is available.
+ ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default if keyboard is not available.
+ ImGuiActivateFlags_TryToPreserveState = 1 << 2 // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
+};
+
enum ImGuiNavHighlightFlags_
{
ImGuiNavHighlightFlags_None = 0,
@@ -1498,12 +1507,14 @@
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
- ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0
+ ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
+ ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustTabbedId; // Just tabbed to this id.
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).
ImGuiKeyModFlags NavJustMovedToKeyMods;
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
+ ImGuiActivateFlags NavNextActivateFlags;
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.
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
@@ -1708,8 +1719,9 @@
CurrentItemFlags = ImGuiItemFlags_None;
NavWindow = NULL;
- NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0;
+ NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
+ NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
NavInputSource = ImGuiInputSource_None;
NavLayer = ImGuiNavLayer_Main;
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index e70a4de..b60676a 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1479,6 +1479,7 @@
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
// Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.
+ // FIXME-TABLE: This work for preserving 2143 into 21|43. How about 4321 turning into 21|43? (preserve relative order in each section)
for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)
{
int order_n = table->DisplayOrderToIndex[column_n];
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 234ba58..6e6d679 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -273,6 +273,7 @@
if (window->SkipItems)
return;
+ // FIXME-OPT: Handle the %s shortcut?
ImGuiContext& g = *GImGui;
const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
@@ -2405,20 +2406,23 @@
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0;
const bool clicked = (hovered && g.IO.MouseClicked[0]);
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
- if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
+ if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
- if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id))
- temp_input_is_active = true;
+ if (temp_input_allowed)
+ if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
+ temp_input_is_active = true;
}
+
// Experimental: simple click (without moving) turns Drag into an InputText
if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
{
- g.NavInputId = id;
+ g.NavActivateId = g.NavActivateInputId = id;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
temp_input_is_active = true;
}
}
@@ -3019,13 +3023,13 @@
{
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0;
const bool clicked = (hovered && g.IO.MouseClicked[0]);
- if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
+ if (focus_requested || clicked || g.NavActivateId == id || g.NavActivateInputId == id)
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
- if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id))
+ if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id))
temp_input_is_active = true;
}
}
@@ -3177,7 +3181,7 @@
format = PatchFormatStringFloatToInt(format);
const bool hovered = ItemHoverable(frame_bb, id);
- if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id)
+ if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavActivateInputId == id)
{
SetActiveID(id, window);
SetFocusID(id, window);
@@ -4019,7 +4023,7 @@
const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool user_clicked = hovered && io.MouseClicked[0];
- const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
+ const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);