IO: avoid changing context in AddKeyAnalogEvent(). Amend 7269498. (#6199, #6256, #4921, #5856)

This commit is contained in:
ocornut
2023-03-21 14:25:34 +01:00
parent 7269498ecc
commit e55a0ef107
3 changed files with 26 additions and 25 deletions

View File

@ -1370,6 +1370,8 @@ static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventT
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
// - bool down: Is the key down? use false to signify a key release.
// - float analog_value: 0.0f..1.0f
// IMPORTANT: THIS FUNCTION AND OTHER "ADD" GRABS THE CONTEXT FROM OUR INSTANCE.
// WE NEED TO ENSURE THAT ALL FUNCTION CALLS ARE FULLFILLING THIS, WHICH IS WHY GetKeyData() HAS AN EXPLICIT CONTEXT.
void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
{
//if (e->Down) { IMGUI_DEBUG_LOG_IO("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); }
@ -1378,7 +1380,7 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
return;
ImGuiContext& g = *Ctx;
IM_ASSERT(ImGui::IsNamedKeyOrModKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API.
IM_ASSERT(!ImGui::IsAliasKey(key)); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events.
IM_ASSERT(ImGui::IsAliasKey(key) == false); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events.
IM_ASSERT(key != ImGuiMod_Shortcut); // We could easily support the translation here but it seems saner to not accept it (TestEngine perform a translation itself)
// Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
@ -1394,10 +1396,7 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
// Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed)
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (int)key);
ImGuiContext* prev_ctx = GImGui;
ImGui::SetCurrentContext(Ctx);
const ImGuiKeyData* key_data = ImGui::GetKeyData(key);
ImGui::SetCurrentContext(prev_ctx);
const ImGuiKeyData* key_data = ImGui::GetKeyData(&g, key);
const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
if (latest_key_down == down && latest_key_analog == analog_value)
@ -7729,13 +7728,13 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
// - Shortcut() [Internal]
//-----------------------------------------------------------------------------
ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key)
ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *ctx;
// Special storage location for mods
if (key & ImGuiMod_Mask_)
key = ConvertSingleModFlagToKey(key);
key = ConvertSingleModFlagToKey(ctx, key);
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
@ -7784,22 +7783,22 @@ IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
const char* ImGui::GetKeyName(ImGuiKey key)
{
ImGuiContext& g = *GImGui;
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT((IsNamedKey(key) || key == ImGuiKey_None) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
#else
if (IsLegacyKey(key))
{
ImGuiIO& io = GetIO();
if (io.KeyMap[key] == -1)
if (g.IO.KeyMap[key] == -1)
return "N/A";
IM_ASSERT(IsNamedKey((ImGuiKey)io.KeyMap[key]));
key = (ImGuiKey)io.KeyMap[key];
IM_ASSERT(IsNamedKey((ImGuiKey)g.IO.KeyMap[key]));
key = (ImGuiKey)g.IO.KeyMap[key];
}
#endif
if (key == ImGuiKey_None)
return "None";
if (key & ImGuiMod_Mask_)
key = ConvertSingleModFlagToKey(key);
key = ConvertSingleModFlagToKey(&g, key);
if (!IsNamedKey(key))
return "Unknown";
@ -7894,7 +7893,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
// Apply routing to owner if there's no owner already (RoutingCurr == None at this point)
if (routing_entry->Mods == g.IO.KeyMods)
{
ImGuiKeyOwnerData* owner_data = ImGui::GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
owner_data->OwnerCurr = routing_entry->RoutingCurr;
}
@ -7931,7 +7930,7 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
if (key == ImGuiKey_None)
key = ConvertSingleModFlagToKey(mods);
key = ConvertSingleModFlagToKey(&g, mods);
IM_ASSERT(IsNamedKey(key));
// Get (in the majority of case, the linked list will have one element so this should be 2 reads.
@ -8801,7 +8800,7 @@ ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
return ImGuiKeyOwner_None;
ImGuiContext& g = *GImGui;
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
ImGuiID owner_id = owner_data->OwnerCurr;
if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any)
@ -8825,7 +8824,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
return false;
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_id == ImGuiKeyOwner_Any)
return (owner_data->LockThisFrame == false);
@ -8853,7 +8852,8 @@ void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
IM_ASSERT(IsNamedKeyOrModKey(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease)))); // Can only use _Any with _LockXXX flags (to eat a key away without an ID to retrieve it)
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function!
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiContext& g = *GImGui;
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
// We cannot lock by default as it would likely break lots of legacy code.
@ -8902,7 +8902,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
// Special storage location for mods
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (key == ImGuiKey_None)
key = ConvertSingleModFlagToKey(mods);
key = ConvertSingleModFlagToKey(&g, mods);
if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_))))
return false;
@ -13728,7 +13728,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
{
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
continue;
Text("%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,