mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-26 05:27:01 +00:00
Internal: Tabbing/Focus: Tidying up old code, moved some state to context instead of window. Storing new data will allow us to fix the bug mentioned in #2215 (probably in next commit).
This commit is contained in:
parent
9c45072cb0
commit
26328fc9fe
78
imgui.cpp
78
imgui.cpp
@ -2552,10 +2552,6 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
|
|||||||
NavLastIds[0] = NavLastIds[1] = 0;
|
NavLastIds[0] = NavLastIds[1] = 0;
|
||||||
NavRectRel[0] = NavRectRel[1] = ImRect();
|
NavRectRel[0] = NavRectRel[1] = ImRect();
|
||||||
NavLastChildNavWindow = NULL;
|
NavLastChildNavWindow = NULL;
|
||||||
|
|
||||||
FocusIdxAllCounter = FocusIdxTabCounter = -1;
|
|
||||||
FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
|
|
||||||
FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindow::~ImGuiWindow()
|
ImGuiWindow::~ImGuiWindow()
|
||||||
@ -2901,22 +2897,28 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
|
|||||||
|
|
||||||
// Increment counters
|
// Increment counters
|
||||||
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
|
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
|
||||||
window->FocusIdxAllCounter++;
|
window->DC.FocusCounterAll++;
|
||||||
if (is_tab_stop)
|
if (is_tab_stop)
|
||||||
window->FocusIdxTabCounter++;
|
window->DC.FocusCounterTab++;
|
||||||
|
|
||||||
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
|
// 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)
|
// (Note that we can always TAB out of a widget that doesn't allow tabbing in)
|
||||||
if (g.ActiveId == id && g.FocusTabPressed && !(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_KeyTab_)))
|
if (g.ActiveId == id && g.FocusTabPressed && !(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_KeyTab_)) && g.FocusRequestNextWindow == NULL)
|
||||||
if (window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX)
|
|
||||||
window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (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.
|
|
||||||
|
|
||||||
if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
|
|
||||||
return true;
|
|
||||||
if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
|
|
||||||
{
|
{
|
||||||
g.NavJustTabbedId = id;
|
g.FocusRequestNextWindow = window;
|
||||||
return true;
|
g.FocusRequestNextCounterTab = window->DC.FocusCounterTab + (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.FocusRequestCurrWindow == window)
|
||||||
|
{
|
||||||
|
if (window->DC.FocusCounterAll == g.FocusRequestCurrCounterAll)
|
||||||
|
return true;
|
||||||
|
if (is_tab_stop && window->DC.FocusCounterTab == g.FocusRequestCurrCounterTab)
|
||||||
|
{
|
||||||
|
g.NavJustTabbedId = id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -2924,8 +2926,8 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
|
|||||||
|
|
||||||
void ImGui::FocusableItemUnregister(ImGuiWindow* window)
|
void ImGui::FocusableItemUnregister(ImGuiWindow* window)
|
||||||
{
|
{
|
||||||
window->FocusIdxAllCounter--;
|
window->DC.FocusCounterAll--;
|
||||||
window->FocusIdxTabCounter--;
|
window->DC.FocusCounterTab--;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
|
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
|
||||||
@ -3515,15 +3517,34 @@ void ImGui::NewFrame()
|
|||||||
UpdateMouseWheel();
|
UpdateMouseWheel();
|
||||||
|
|
||||||
// Pressing TAB activate widget focus
|
// Pressing TAB activate widget focus
|
||||||
// (This code is old and will be redesigned for Nav. In the meanwhile we use g.NavTabRequest as storage but this doesn't need ImGuiConfigFlags_NavEnableKeyboard to work!)
|
|
||||||
g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
|
g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
|
||||||
if (g.ActiveId == 0 && g.FocusTabPressed)
|
if (g.ActiveId == 0 && g.FocusTabPressed)
|
||||||
{
|
{
|
||||||
|
// Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
|
||||||
|
// manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
|
||||||
|
g.FocusRequestNextWindow = g.NavWindow;
|
||||||
|
g.FocusRequestNextCounterAll = INT_MAX;
|
||||||
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
||||||
g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
g.FocusRequestNextCounterTab = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
||||||
else
|
else
|
||||||
g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0;
|
g.FocusRequestNextCounterTab = g.IO.KeyShift ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn queued focus request into current one
|
||||||
|
g.FocusRequestCurrWindow = NULL;
|
||||||
|
g.FocusRequestCurrCounterAll = g.FocusRequestCurrCounterTab = INT_MAX;
|
||||||
|
if (g.FocusRequestNextWindow != NULL)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = g.FocusRequestNextWindow;
|
||||||
|
g.FocusRequestCurrWindow = window;
|
||||||
|
if (g.FocusRequestNextCounterAll != INT_MAX && window->DC.FocusCounterAll != -1)
|
||||||
|
g.FocusRequestCurrCounterAll = ImModPositive(g.FocusRequestNextCounterAll, window->DC.FocusCounterAll + 1);
|
||||||
|
if (g.FocusRequestNextCounterTab != INT_MAX && window->DC.FocusCounterTab != -1)
|
||||||
|
g.FocusRequestCurrCounterTab = ImModPositive(g.FocusRequestNextCounterTab, window->DC.FocusCounterTab + 1);
|
||||||
|
g.FocusRequestNextWindow = NULL;
|
||||||
|
g.FocusRequestNextCounterAll = g.FocusRequestNextCounterTab = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
g.NavIdTabCounter = INT_MAX;
|
g.NavIdTabCounter = INT_MAX;
|
||||||
|
|
||||||
// Mark all windows as not visible
|
// Mark all windows as not visible
|
||||||
@ -5170,12 +5191,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
// Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
|
// Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
|
||||||
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
||||||
|
|
||||||
// Prepare for item focus requests
|
|
||||||
window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : ImModPositive(window->FocusIdxAllRequestNext, window->FocusIdxAllCounter + 1);
|
|
||||||
window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : ImModPositive(window->FocusIdxTabRequestNext, window->FocusIdxTabCounter + 1);
|
|
||||||
window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
|
|
||||||
window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
|
|
||||||
|
|
||||||
// Apply scrolling
|
// Apply scrolling
|
||||||
window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
|
window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
|
||||||
window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
|
window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
|
||||||
@ -5350,6 +5365,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
window->DC.ChildWindows.resize(0);
|
window->DC.ChildWindows.resize(0);
|
||||||
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.FocusCounterAll = window->DC.FocusCounterTab = -1;
|
||||||
window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
|
window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
|
||||||
window->DC.ItemWidth = window->ItemWidthDefault;
|
window->DC.ItemWidth = window->ItemWidthDefault;
|
||||||
window->DC.TextWrapPos = -1.0f; // disabled
|
window->DC.TextWrapPos = -1.0f; // disabled
|
||||||
@ -6462,9 +6478,11 @@ void ImGui::ActivateItem(ImGuiID id)
|
|||||||
void ImGui::SetKeyboardFocusHere(int offset)
|
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
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiContext& g = *GImGui;
|
||||||
window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
window->FocusIdxTabRequestNext = INT_MAX;
|
g.FocusRequestNextWindow = window;
|
||||||
|
g.FocusRequestNextCounterAll = window->DC.FocusCounterAll + 1 + offset;
|
||||||
|
g.FocusRequestNextCounterTab = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::SetItemDefaultFocus()
|
void ImGui::SetItemDefaultFocus()
|
||||||
@ -7373,7 +7391,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
|
|||||||
g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
|
g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
|
||||||
g.NavLayer = window->DC.NavLayerCurrent;
|
g.NavLayer = window->DC.NavLayerCurrent;
|
||||||
g.NavIdIsAlive = true;
|
g.NavIdIsAlive = true;
|
||||||
g.NavIdTabCounter = window->FocusIdxTabCounter;
|
g.NavIdTabCounter = window->DC.FocusCounterTab;
|
||||||
window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
|
window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -892,7 +892,13 @@ struct ImGuiContext
|
|||||||
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)
|
||||||
|
|
||||||
// Tabbing system (older than Nav, active when Nav is disabled. Probably needs a redesign)
|
// Tabbing system (older than Nav, active even if Nav is disabled. FIXME-NAV: This needs a redesign!)
|
||||||
|
ImGuiWindow* FocusRequestCurrWindow; //
|
||||||
|
ImGuiWindow* FocusRequestNextWindow; //
|
||||||
|
int FocusRequestCurrCounterAll; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
|
||||||
|
int FocusRequestCurrCounterTab; // Tab item being requested for focus, stored as an index
|
||||||
|
int FocusRequestNextCounterAll; // Stored for next frame
|
||||||
|
int FocusRequestNextCounterTab; // "
|
||||||
bool FocusTabPressed; //
|
bool FocusTabPressed; //
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@ -1040,6 +1046,10 @@ struct ImGuiContext
|
|||||||
NavMoveRequestFlags = 0;
|
NavMoveRequestFlags = 0;
|
||||||
NavMoveRequestForward = ImGuiNavForward_None;
|
NavMoveRequestForward = ImGuiNavForward_None;
|
||||||
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
||||||
|
|
||||||
|
FocusRequestCurrWindow = FocusRequestNextWindow = NULL;
|
||||||
|
FocusRequestCurrCounterAll = FocusRequestCurrCounterTab = INT_MAX;
|
||||||
|
FocusRequestNextCounterAll = FocusRequestNextCounterTab = INT_MAX;
|
||||||
FocusTabPressed = false;
|
FocusTabPressed = false;
|
||||||
|
|
||||||
DimBgRatio = 0.0f;
|
DimBgRatio = 0.0f;
|
||||||
@ -1127,6 +1137,8 @@ struct IMGUI_API ImGuiWindowTempData
|
|||||||
ImGuiStorage* StateStorage;
|
ImGuiStorage* StateStorage;
|
||||||
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 FocusCounterAll; // Counter for focus/tabbing system. Start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign)
|
||||||
|
int FocusCounterTab; // (same, but only count widgets which you can Tab through)
|
||||||
|
|
||||||
// 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.
|
||||||
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
|
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
|
||||||
@ -1162,8 +1174,10 @@ struct IMGUI_API ImGuiWindowTempData
|
|||||||
MenuBarOffset = ImVec2(0.0f, 0.0f);
|
MenuBarOffset = ImVec2(0.0f, 0.0f);
|
||||||
StateStorage = NULL;
|
StateStorage = NULL;
|
||||||
LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical;
|
LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical;
|
||||||
ItemWidth = 0.0f;
|
FocusCounterAll = FocusCounterTab = -1;
|
||||||
|
|
||||||
ItemFlags = ImGuiItemFlags_Default_;
|
ItemFlags = ImGuiItemFlags_Default_;
|
||||||
|
ItemWidth = 0.0f;
|
||||||
TextWrapPos = -1.0f;
|
TextWrapPos = -1.0f;
|
||||||
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
|
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
|
||||||
|
|
||||||
@ -1248,15 +1262,6 @@ struct IMGUI_API ImGuiWindow
|
|||||||
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
|
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
|
||||||
ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
|
ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
|
||||||
|
|
||||||
// Navigation / Focus
|
|
||||||
// FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext
|
|
||||||
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
|
|
||||||
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
|
|
||||||
int FocusIdxAllRequestCurrent; // Item being requested for focus
|
|
||||||
int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
|
|
||||||
int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
|
|
||||||
int FocusIdxTabRequestNext; // "
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImGuiWindow(ImGuiContext* context, const char* name);
|
ImGuiWindow(ImGuiContext* context, const char* name);
|
||||||
~ImGuiWindow();
|
~ImGuiWindow();
|
||||||
|
@ -3275,7 +3275,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
state = &g.InputTextState;
|
state = &g.InputTextState;
|
||||||
|
|
||||||
const bool focus_requested = FocusableItemRegister(window, id);
|
const bool focus_requested = FocusableItemRegister(window, id);
|
||||||
const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
|
const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterAll == window->DC.FocusCounterAll);
|
||||||
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
|
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
|
||||||
|
|
||||||
const bool user_clicked = hovered && io.MouseClicked[0];
|
const bool user_clicked = hovered && io.MouseClicked[0];
|
||||||
|
Loading…
Reference in New Issue
Block a user