mirror of
https://github.com/ocornut/imgui.git
synced 2025-02-08 23:19:40 +01:00
Fixed IsItemDeactivated(), IsItemDeactivatedAfterEdit() to work when interrupted before/after the active id is submitted. (#5184, #5904, #6766, #8303, #8004)
This commit is contained in:
parent
a28ffa81c4
commit
a604d4f717
@ -43,6 +43,15 @@ Breaking changes:
|
|||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
|
|
||||||
|
- Fixed issues with IsItemDeactivated() and IsItemDeactivatedAfterEdit() not
|
||||||
|
emitting a reliable signal when an item is deactivated externally: e.g.
|
||||||
|
via an explicit clear of focus, clear of active id, opening of modal etc.
|
||||||
|
(#5184, #5904, #6766, #8303, #8004)
|
||||||
|
- It used to work when the interruption happened in the frame before the
|
||||||
|
active item as submitted, but not after. It should work in both cases now.
|
||||||
|
- While this is not specific to a certain widgets, typically it would
|
||||||
|
mostly be noticeable on InputText() because it keeps ActiveId for a
|
||||||
|
longer time while allowing other interaction to happen.
|
||||||
- Error Handling: Fixed bugs recovering from within a table that created
|
- Error Handling: Fixed bugs recovering from within a table that created
|
||||||
a child window, and from nested child windows. (#1651)
|
a child window, and from nested child windows. (#1651)
|
||||||
- Error Handling: Turned common EndTable() and other TableXXX functions
|
- Error Handling: Turned common EndTable() and other TableXXX functions
|
||||||
|
40
imgui.cpp
40
imgui.cpp
@ -3930,9 +3930,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
ActiveIdSource = ImGuiInputSource_None;
|
ActiveIdSource = ImGuiInputSource_None;
|
||||||
ActiveIdMouseButton = -1;
|
ActiveIdMouseButton = -1;
|
||||||
ActiveIdPreviousFrame = 0;
|
ActiveIdPreviousFrame = 0;
|
||||||
ActiveIdPreviousFrameIsAlive = false;
|
memset(&DeactivatedItemData, 0, sizeof(DeactivatedItemData));
|
||||||
ActiveIdPreviousFrameHasBeenEditedBefore = false;
|
|
||||||
ActiveIdPreviousFrameWindow = NULL;
|
|
||||||
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
|
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
|
||||||
LastActiveId = 0;
|
LastActiveId = 0;
|
||||||
LastActiveIdTimer = 0.0f;
|
LastActiveIdTimer = 0.0f;
|
||||||
@ -4175,7 +4173,7 @@ void ImGui::Shutdown()
|
|||||||
g.WindowsById.Clear();
|
g.WindowsById.Clear();
|
||||||
g.NavWindow = NULL;
|
g.NavWindow = NULL;
|
||||||
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
||||||
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
|
g.ActiveIdWindow = NULL;
|
||||||
g.MovingWindow = NULL;
|
g.MovingWindow = NULL;
|
||||||
|
|
||||||
g.KeysRoutingTable.Clear();
|
g.KeysRoutingTable.Clear();
|
||||||
@ -4359,6 +4357,13 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
|||||||
g.MovingWindow = NULL;
|
g.MovingWindow = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store deactivate data
|
||||||
|
ImGuiDeactivatedItemData* deactivated_data = &g.DeactivatedItemData;
|
||||||
|
deactivated_data->ID = g.ActiveId;
|
||||||
|
deactivated_data->ElapseFrame = (g.LastItemData.ID == g.ActiveId) ? g.FrameCount : g.FrameCount + 1; // FIXME: OK to use LastItemData?
|
||||||
|
deactivated_data->HasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
|
||||||
|
deactivated_data->IsAlive = (g.ActiveIdIsAlive == g.ActiveId);
|
||||||
|
|
||||||
// This could be written in a more general way (e.g associate a hook to ActiveId),
|
// This could be written in a more general way (e.g associate a hook to ActiveId),
|
||||||
// but since this is currently quite an exception we'll leave it as is.
|
// but since this is currently quite an exception we'll leave it as is.
|
||||||
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
|
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
|
||||||
@ -5189,11 +5194,8 @@ void ImGui::NewFrame()
|
|||||||
g.ActiveIdTimer += g.IO.DeltaTime;
|
g.ActiveIdTimer += g.IO.DeltaTime;
|
||||||
g.LastActiveIdTimer += g.IO.DeltaTime;
|
g.LastActiveIdTimer += g.IO.DeltaTime;
|
||||||
g.ActiveIdPreviousFrame = g.ActiveId;
|
g.ActiveIdPreviousFrame = g.ActiveId;
|
||||||
g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
|
|
||||||
g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
|
|
||||||
g.ActiveIdIsAlive = 0;
|
g.ActiveIdIsAlive = 0;
|
||||||
g.ActiveIdHasBeenEditedThisFrame = false;
|
g.ActiveIdHasBeenEditedThisFrame = false;
|
||||||
g.ActiveIdPreviousFrameIsAlive = false;
|
|
||||||
g.ActiveIdIsJustActivated = false;
|
g.ActiveIdIsJustActivated = false;
|
||||||
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
|
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
|
||||||
g.TempInputId = 0;
|
g.TempInputId = 0;
|
||||||
@ -5202,6 +5204,9 @@ void ImGui::NewFrame()
|
|||||||
g.ActiveIdUsingNavDirMask = 0x00;
|
g.ActiveIdUsingNavDirMask = 0x00;
|
||||||
g.ActiveIdUsingAllKeyboardKeys = false;
|
g.ActiveIdUsingAllKeyboardKeys = false;
|
||||||
}
|
}
|
||||||
|
if (g.DeactivatedItemData.ElapseFrame < g.FrameCount)
|
||||||
|
g.DeactivatedItemData.ID = 0;
|
||||||
|
g.DeactivatedItemData.IsAlive = false;
|
||||||
|
|
||||||
// Record when we have been stationary as this state is preserved while over same item.
|
// Record when we have been stationary as this state is preserved while over same item.
|
||||||
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
|
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
|
||||||
@ -5833,13 +5838,13 @@ bool ImGui::IsItemDeactivated()
|
|||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
|
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
|
||||||
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
|
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
|
||||||
return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID);
|
return (g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 && g.DeactivatedItemData.ElapseFrame >= g.FrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui::IsItemDeactivatedAfterEdit()
|
bool ImGui::IsItemDeactivatedAfterEdit()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
|
return IsItemDeactivated() && g.DeactivatedItemData.HasBeenEditedBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
// == (GetItemID() == GetFocusID() && GetFocusID() != 0)
|
// == (GetItemID() == GetFocusID() && GetFocusID() != 0)
|
||||||
@ -10443,8 +10448,8 @@ void ImGui::KeepAliveID(ImGuiID id)
|
|||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
g.ActiveIdIsAlive = id;
|
g.ActiveIdIsAlive = id;
|
||||||
if (g.ActiveIdPreviousFrame == id)
|
if (g.DeactivatedItemData.ID == id)
|
||||||
g.ActiveIdPreviousFrameIsAlive = true;
|
g.DeactivatedItemData.IsAlive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declare item bounding box for clipping and interaction.
|
// Declare item bounding box for clipping and interaction.
|
||||||
@ -10529,6 +10534,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|||||||
// window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
|
// window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (id != 0 && g.DeactivatedItemData.ID == id)
|
||||||
|
g.DeactivatedItemData.ElapseFrame = g.FrameCount;
|
||||||
|
|
||||||
// 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 (is_rect_visible)
|
if (is_rect_visible)
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
|
||||||
@ -10888,7 +10896,7 @@ void ImGui::BeginGroup()
|
|||||||
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
||||||
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
|
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
|
||||||
group_data.BackupIsSameLine = window->DC.IsSameLine;
|
group_data.BackupIsSameLine = window->DC.IsSameLine;
|
||||||
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
|
group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
|
||||||
group_data.EmitItem = true;
|
group_data.EmitItem = true;
|
||||||
|
|
||||||
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
|
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
|
||||||
@ -10939,11 +10947,11 @@ void ImGui::EndGroup()
|
|||||||
// Also if you grep for LastItemId you'll notice it is only used in that context.
|
// Also if you grep for LastItemId you'll notice it is only used in that context.
|
||||||
// (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
|
// (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
|
||||||
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
|
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
|
||||||
const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true);
|
const bool group_contains_deactivated_id = (group_data.BackupDeactivatedIdIsAlive == false) && (g.DeactivatedItemData.IsAlive == true);
|
||||||
if (group_contains_curr_active_id)
|
if (group_contains_curr_active_id)
|
||||||
g.LastItemData.ID = g.ActiveId;
|
g.LastItemData.ID = g.ActiveId;
|
||||||
else if (group_contains_prev_active_id)
|
else if (group_contains_deactivated_id)
|
||||||
g.LastItemData.ID = g.ActiveIdPreviousFrame;
|
g.LastItemData.ID = g.DeactivatedItemData.ID;
|
||||||
g.LastItemData.Rect = group_bb;
|
g.LastItemData.Rect = group_bb;
|
||||||
|
|
||||||
// Forward Hovered flag
|
// Forward Hovered flag
|
||||||
@ -10957,7 +10965,7 @@ void ImGui::EndGroup()
|
|||||||
|
|
||||||
// Forward Deactivated flag
|
// Forward Deactivated flag
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
|
||||||
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
|
if (group_contains_deactivated_id)
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
|
||||||
|
|
||||||
g.GroupStack.pop_back();
|
g.GroupStack.pop_back();
|
||||||
|
2
imgui.h
2
imgui.h
@ -29,7 +29,7 @@
|
|||||||
// Library Version
|
// Library Version
|
||||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||||
#define IMGUI_VERSION "1.91.7 WIP"
|
#define IMGUI_VERSION "1.91.7 WIP"
|
||||||
#define IMGUI_VERSION_NUM 19164
|
#define IMGUI_VERSION_NUM 19165
|
||||||
#define IMGUI_HAS_TABLE
|
#define IMGUI_HAS_TABLE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -140,6 +140,7 @@ struct ImGuiContext; // Main Dear ImGui context
|
|||||||
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
|
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
|
||||||
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
|
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
|
||||||
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
|
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
|
||||||
|
struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function.
|
||||||
struct ImGuiErrorRecoveryState; // Storage of stack sizes for error handling and recovery
|
struct ImGuiErrorRecoveryState; // Storage of stack sizes for error handling and recovery
|
||||||
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
|
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
|
||||||
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
|
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
|
||||||
@ -1070,7 +1071,7 @@ struct IMGUI_API ImGuiGroupData
|
|||||||
ImVec2 BackupCurrLineSize;
|
ImVec2 BackupCurrLineSize;
|
||||||
float BackupCurrLineTextBaseOffset;
|
float BackupCurrLineTextBaseOffset;
|
||||||
ImGuiID BackupActiveIdIsAlive;
|
ImGuiID BackupActiveIdIsAlive;
|
||||||
bool BackupActiveIdPreviousFrameIsAlive;
|
bool BackupDeactivatedIdIsAlive;
|
||||||
bool BackupHoveredIdIsAlive;
|
bool BackupHoveredIdIsAlive;
|
||||||
bool BackupIsSameLine;
|
bool BackupIsSameLine;
|
||||||
bool EmitItem;
|
bool EmitItem;
|
||||||
@ -1314,6 +1315,15 @@ struct ImGuiPtrOrIndex
|
|||||||
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
|
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
|
||||||
|
struct ImGuiDeactivatedItemData
|
||||||
|
{
|
||||||
|
ImGuiID ID;
|
||||||
|
int ElapseFrame;
|
||||||
|
bool HasBeenEditedBefore;
|
||||||
|
bool IsAlive;
|
||||||
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Popup support
|
// [SECTION] Popup support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2106,9 +2116,7 @@ struct ImGuiContext
|
|||||||
ImGuiWindow* ActiveIdWindow;
|
ImGuiWindow* ActiveIdWindow;
|
||||||
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
|
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
|
||||||
ImGuiID ActiveIdPreviousFrame;
|
ImGuiID ActiveIdPreviousFrame;
|
||||||
bool ActiveIdPreviousFrameIsAlive;
|
ImGuiDeactivatedItemData DeactivatedItemData;
|
||||||
bool ActiveIdPreviousFrameHasBeenEditedBefore;
|
|
||||||
ImGuiWindow* ActiveIdPreviousFrameWindow;
|
|
||||||
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
|
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
|
||||||
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
|
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
|
||||||
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
|
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user