From ccf0cc85840a5edbeb7c4450cfd67949d0534512 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 19 Mar 2020 12:24:32 +0100 Subject: [PATCH] Added ImGuiKeyModFlags. Added additional checks in EndFrame() to verify that io.KeyXXX values have not been tampered with between NewFrame() and EndFrame(). --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 21 ++++++++++++++++++++- imgui.h | 12 ++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c5d70d0b..96d02a88 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other Changes: - Window: Fixed a bug with child window inheriting ItemFlags from their parent when the child window also manipulate the ItemFlags stack. (#3024) [@Stanbroek] - Font: Fixed non-ASCII space occasionally creating unnecessary empty polygons. +- Misc: Added additional checks in EndFrame() to verify that io.KeyXXX values have not been + tampered with between NewFrame() and EndFrame(). - Misc, Freetype: Fixed support for IMGUI_STB_RECT_PACK_FILENAME compile time directive in imgui_freetype.cpp (matching support in the regular code path). (#3062) [@DonKult] - Demo: Added black and white and color gradients to Demo>Examples>Custom Rendering. diff --git a/imgui.cpp b/imgui.cpp index 7a0954a1..d7872164 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3704,6 +3704,17 @@ static void NewFrameSanityChecks() g.IO.ConfigWindowsResizeFromEdges = false; } +static ImGuiKeyModFlags GetMergedKeyModFlags() +{ + ImGuiContext& g = *GImGui; + ImGuiKeyModFlags key_mod_flags = ImGuiKeyModFlags_None; + if (g.IO.KeyCtrl) { key_mod_flags |= ImGuiKeyModFlags_Ctrl; } + if (g.IO.KeyShift) { key_mod_flags |= ImGuiKeyModFlags_Shift; } + if (g.IO.KeyAlt) { key_mod_flags |= ImGuiKeyModFlags_Alt; } + if (g.IO.KeySuper) { key_mod_flags |= ImGuiKeyModFlags_Super; } + return key_mod_flags; +} + void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); @@ -3805,6 +3816,8 @@ void ImGui::NewFrame() g.DragDropWithinTarget = false; // Update keyboard input state + // Synchronize io.KeyMods with individual modifiers io.KeyXXX bools + g.IO.KeyMods = GetMergedKeyModFlags(); memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; @@ -6720,9 +6733,15 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si static void ImGui::ErrorCheckEndFrame() { + ImGuiContext& g = *GImGui; + + // Verify that io.KeyXXX fields haven't been tampered with. Key mods shoudl not be modified between NewFrame() and EndFrame() + const ImGuiKeyModFlags expected_key_mod_flags = GetMergedKeyModFlags(); + IM_ASSERT(g.IO.KeyMods == expected_key_mod_flags && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); + IM_UNUSED(expected_key_mod_flags); + // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). - ImGuiContext& g = *GImGui; if (g.CurrentWindowStack.Size != 1) { if (g.CurrentWindowStack.Size > 1) diff --git a/imgui.h b/imgui.h index 70798230..d45e873b 100644 --- a/imgui.h +++ b/imgui.h @@ -168,6 +168,7 @@ typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: f typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() +typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super) typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem() @@ -997,6 +998,16 @@ enum ImGuiKey_ ImGuiKey_COUNT }; +// To test io.KeyMods (which is a combination of individual fields io.KeyCtrl, io.KeyShift, io.KeyAlt set by user/back-end) +enum ImGuiKeyModFlags_ +{ + ImGuiKeyModFlags_None = 0, + ImGuiKeyModFlags_Ctrl = 1 << 0, + ImGuiKeyModFlags_Shift = 1 << 1, + ImGuiKeyModFlags_Alt = 1 << 2, + ImGuiKeyModFlags_Super = 1 << 3 +}; + // Gamepad/Keyboard directional navigation // Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. // Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Back-end: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). @@ -1496,6 +1507,7 @@ struct ImGuiIO // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ + ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame() ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MouseClickedPos[5]; // Position at time of clicking double MouseClickedTime[5]; // Time of last click (used to figure out double-click)