Pārlūkot izejas kodu

IO: Fixed input queue trickling of interleaved keys/chars events when InputText() is not active. (#4921, #4858)

ocornut 3 gadi atpakaļ
vecāks
revīzija
fa2b318dd6
3 mainītis faili ar 35 papildinājumiem un 6 dzēšanām
  1. 8 0
      docs/CHANGELOG.txt
  2. 26 5
      imgui.cpp
  3. 1 1
      imgui.h

+ 8 - 0
docs/CHANGELOG.txt

@@ -43,6 +43,14 @@ Other Changes:
   - Direct accesses to io.KeysDown[] with legacy indices didn't work (with new backends).
   - Direct accesses to io.KeysDown[] with legacy indices didn't work (with new backends).
   - Direct accesses to io.KeysDown[GetKeyIndex(XXX)] would access invalid data (with old/new backends).
   - Direct accesses to io.KeysDown[GetKeyIndex(XXX)] would access invalid data (with old/new backends).
   - Calling IsKeyDown() didn't have those problems, and is recommended as io.KeysDown[] is obsolete.
   - Calling IsKeyDown() didn't have those problems, and is recommended as io.KeysDown[] is obsolete.
+- IO: Fixed input queue trickling of interleaved keys/chars events (which are frequent especially
+  when holding down a key as OS submits chars repeat events) delaying key presses and mouse movements.
+  In particular, using the input system for fast game-like actions (e.g. WASD camera move) would
+  typically have been impacted, as well as holding a key while dragging mouse. Constraints have
+  been lifted and are now only happening when e.g. an InputText() widget is active. (#4921, #4858)
+  Not that even thought you shouldn't need to disable io.ConfigInputTrickleEventQueue, you can
+  technically dynamically change its setting based on the context (e.g. disable only when hovering
+  or interacting with a game/3D view).
 - Clipper: Fixed a regression in 1.86 when not calling clipper.End() and late destructing the
 - Clipper: Fixed a regression in 1.86 when not calling clipper.End() and late destructing the
   clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822)
   clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822)
 - IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the
 - IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the

+ 26 - 5
imgui.cpp

@@ -7799,8 +7799,18 @@ static const char* GetInputSourceName(ImGuiInputSource source)
     return input_source_names[source];
     return input_source_names[source];
 }
 }
 
 
+/*static void DebugLogInputEvent(const char* prefix, const ImGuiInputEvent* e)
+{
+    if (e->Type == ImGuiInputEventType_MousePos)    { IMGUI_DEBUG_LOG("%s: MousePos (%.1f %.1f)\n", prefix, e->MousePos.PosX, e->MousePos.PosY); return; }
+    if (e->Type == ImGuiInputEventType_MouseButton) { IMGUI_DEBUG_LOG("%s: MouseButton %d %s\n", prefix, e->MouseButton.Button, e->MouseButton.Down ? "Down" : "Up"); return; }
+    if (e->Type == ImGuiInputEventType_MouseWheel)  { IMGUI_DEBUG_LOG("%s: MouseWheel (%.1f %.1f)\n", prefix, e->MouseWheel.WheelX, e->MouseWheel.WheelY); return; }
+    if (e->Type == ImGuiInputEventType_Key)         { IMGUI_DEBUG_LOG("%s: Key \"%s\" %s\n", prefix, ImGui::GetKeyName(e->Key.Key), e->Key.Down ? "Down" : "Up"); return; }
+    if (e->Type == ImGuiInputEventType_Text)        { IMGUI_DEBUG_LOG("%s: Text: %c (U+%08X)\n", prefix, e->Text.Char, e->Text.Char); return; }
+    if (e->Type == ImGuiInputEventType_Focus)       { IMGUI_DEBUG_LOG("%s: AppFocused %d\n", prefix, e->AppFocused.Focused); return; }
+}*/
 
 
 // Process input queue
 // Process input queue
+// We always call this with the value of 'bool g.IO.ConfigInputTrickleEventQueue'.
 // - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost)
 // - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost)
 // - trickle_fast_inputs = true  : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87)
 // - trickle_fast_inputs = true  : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87)
 void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
 void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
@@ -7808,7 +7818,12 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
     ImGuiContext& g = *GImGui;
     ImGuiContext& g = *GImGui;
     ImGuiIO& io = g.IO;
     ImGuiIO& io = g.IO;
 
 
-    bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputed = false;
+    // Only trickle chars<>key when working with InputText()
+    // FIXME: InputText() could parse event trail?
+    // FIXME: Could specialize chars<>keys trickling rules for control keys (those not typically associated to characters)
+    const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1);
+
+    bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputted = false;
     int  mouse_button_changed = 0x00;
     int  mouse_button_changed = 0x00;
     ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
     ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
 
 
@@ -7824,7 +7839,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
             if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y)
             if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y)
             {
             {
                 // Trickling Rule: Stop processing queued events if we already handled a mouse button change
                 // Trickling Rule: Stop processing queued events if we already handled a mouse button change
-                if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputed))
+                if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
                     break;
                     break;
                 io.MousePos = event_pos;
                 io.MousePos = event_pos;
                 mouse_moved = true;
                 mouse_moved = true;
@@ -7864,7 +7879,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
             if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.AnalogValue)
             if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.AnalogValue)
             {
             {
                 // Trickling Rule: Stop processing queued events if we got multiple action on the same button
                 // Trickling Rule: Stop processing queued events if we got multiple action on the same button
-                if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0))
+                if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputted || mouse_button_changed != 0))
                     break;
                     break;
                 keydata->Down = e->Key.Down;
                 keydata->Down = e->Key.Down;
                 keydata->AnalogValue = e->Key.AnalogValue;
                 keydata->AnalogValue = e->Key.AnalogValue;
@@ -7891,11 +7906,12 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
         else if (e->Type == ImGuiInputEventType_Text)
         else if (e->Type == ImGuiInputEventType_Text)
         {
         {
             // Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
             // Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
-            if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
+            if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
                 break;
                 break;
             unsigned int c = e->Text.Char;
             unsigned int c = e->Text.Char;
             io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
             io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
-            text_inputed = true;
+            if (trickle_interleaved_keys_and_text)
+                text_inputted = true;
         }
         }
         else if (e->Type == ImGuiInputEventType_Focus)
         else if (e->Type == ImGuiInputEventType_Focus)
         {
         {
@@ -7914,6 +7930,11 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
     for (int n = 0; n < event_n; n++)
     for (int n = 0; n < event_n; n++)
         g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
         g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
 
 
+    // [DEBUG]
+    /*if (event_n != 0)
+        for (int n = 0; n < g.InputEventsQueue.Size; n++)
+            DebugLogInputEvent(n < event_n ? "Processed" : "Remaining", &g.InputEventsQueue[n]);*/
+
     // Remaining events will be processed on the next frame
     // Remaining events will be processed on the next frame
     if (event_n == g.InputEventsQueue.Size)
     if (event_n == g.InputEventsQueue.Size)
         g.InputEventsQueue.resize(0);
         g.InputEventsQueue.resize(0);

+ 1 - 1
imgui.h

@@ -65,7 +65,7 @@ Index of this file:
 // Version
 // Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
 #define IMGUI_VERSION               "1.88 WIP"
 #define IMGUI_VERSION               "1.88 WIP"
-#define IMGUI_VERSION_NUM           18708
+#define IMGUI_VERSION_NUM           18709
 #define IMGUI_CHECKVERSION()        ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
 #define IMGUI_CHECKVERSION()        ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
 #define IMGUI_HAS_TABLE
 #define IMGUI_HAS_TABLE