Skip to content

Commit 7b0d58c

Browse files
committed
Merge branch 'master' into docking
2 parents 9948535 + fa2b318 commit 7b0d58c

File tree

5 files changed

+79
-29
lines changed

5 files changed

+79
-29
lines changed

backends/imgui_impl_osx.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
650650
wheel_dx = [event deltaX];
651651
wheel_dy = [event deltaY];
652652
}
653-
if (wheel_dx != 0.0 || wheel_dx != 0.0)
653+
if (wheel_dx != 0.0 || wheel_dy != 0.0)
654654
io.AddMouseWheelEvent((float)wheel_dx * 0.1f, (float)wheel_dy * 0.1f);
655655

656656
return io.WantCaptureMouse;

docs/CHANGELOG.txt

+12
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ Breaking changes:
106106

107107
Other Changes:
108108

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

imgui.cpp

+44-11
Original file line numberDiff line numberDiff line change
@@ -1357,8 +1357,10 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native
13571357
// Build native->imgui map so old user code can still call key functions with native 0..511 values.
13581358
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
13591359
const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
1360-
if (ImGui::IsLegacyKey(legacy_key))
1361-
KeyMap[legacy_key] = key;
1360+
if (!ImGui::IsLegacyKey(legacy_key))
1361+
return;
1362+
KeyMap[legacy_key] = key;
1363+
KeyMap[key] = legacy_key;
13621364
#else
13631365
IM_UNUSED(key);
13641366
IM_UNUSED(native_legacy_index);
@@ -2648,6 +2650,7 @@ bool ImGuiListClipper::Step()
26482650
ImGuiContext& g = *GImGui;
26492651
ImGuiWindow* window = g.CurrentWindow;
26502652
ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
2653+
IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
26512654

26522655
ImGuiTable* table = g.CurrentTable;
26532656
if (table && table->IsInsideRow)
@@ -4094,9 +4097,9 @@ static void ImGui::UpdateKeyboardInputs()
40944097
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
40954098
if (io.BackendUsingLegacyKeyArrays == 0)
40964099
{
4097-
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written too.
4098-
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++)
4099-
IM_ASSERT(io.KeysDown[n] == false && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
4100+
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally.
4101+
for (int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
4102+
IM_ASSERT((io.KeysDown[n] == false || IsKeyDown(n)) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
41004103
}
41014104
else
41024105
{
@@ -4119,6 +4122,8 @@ static void ImGui::UpdateKeyboardInputs()
41194122
const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
41204123
IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
41214124
io.KeysData[key].Down = io.KeysDown[n];
4125+
if (key != n)
4126+
io.KeysDown[key] = io.KeysDown[n]; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends
41224127
io.BackendUsingLegacyKeyArrays = 1;
41234128
}
41244129
if (io.BackendUsingLegacyKeyArrays == 1)
@@ -8391,16 +8396,31 @@ static const char* GetInputSourceName(ImGuiInputSource source)
83918396
return input_source_names[source];
83928397
}
83938398

8399+
/*static void DebugLogInputEvent(const char* prefix, const ImGuiInputEvent* e)
8400+
{
8401+
if (e->Type == ImGuiInputEventType_MousePos) { IMGUI_DEBUG_LOG("%s: MousePos (%.1f %.1f)\n", prefix, e->MousePos.PosX, e->MousePos.PosY); return; }
8402+
if (e->Type == ImGuiInputEventType_MouseButton) { IMGUI_DEBUG_LOG("%s: MouseButton %d %s\n", prefix, e->MouseButton.Button, e->MouseButton.Down ? "Down" : "Up"); return; }
8403+
if (e->Type == ImGuiInputEventType_MouseWheel) { IMGUI_DEBUG_LOG("%s: MouseWheel (%.1f %.1f)\n", prefix, e->MouseWheel.WheelX, e->MouseWheel.WheelY); return; }
8404+
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; }
8405+
if (e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG("%s: Text: %c (U+%08X)\n", prefix, e->Text.Char, e->Text.Char); return; }
8406+
if (e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG("%s: AppFocused %d\n", prefix, e->AppFocused.Focused); return; }
8407+
}*/
83948408

83958409
// Process input queue
8410+
// We always call this with the value of 'bool g.IO.ConfigInputTrickleEventQueue'.
83968411
// - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost)
83978412
// - 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)
83988413
void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
83998414
{
84008415
ImGuiContext& g = *GImGui;
84018416
ImGuiIO& io = g.IO;
84028417

8403-
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputed = false;
8418+
// Only trickle chars<>key when working with InputText()
8419+
// FIXME: InputText() could parse event trail?
8420+
// FIXME: Could specialize chars<>keys trickling rules for control keys (those not typically associated to characters)
8421+
const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1);
8422+
8423+
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputted = false;
84048424
int mouse_button_changed = 0x00;
84058425
ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
84068426

@@ -8416,7 +8436,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
84168436
if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y)
84178437
{
84188438
// Trickling Rule: Stop processing queued events if we already handled a mouse button change
8419-
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputed))
8439+
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
84208440
break;
84218441
io.MousePos = event_pos;
84228442
mouse_moved = true;
@@ -8460,7 +8480,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
84608480
if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.AnalogValue)
84618481
{
84628482
// Trickling Rule: Stop processing queued events if we got multiple action on the same button
8463-
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0))
8483+
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputted || mouse_button_changed != 0))
84648484
break;
84658485
keydata->Down = e->Key.Down;
84668486
keydata->AnalogValue = e->Key.AnalogValue;
@@ -8475,16 +8495,24 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
84758495
if (key == ImGuiKey_ModSuper) { io.KeySuper = keydata->Down; }
84768496
io.KeyMods = GetMergedKeyModFlags();
84778497
}
8498+
8499+
// Allow legacy code using io.KeysDown[GetKeyIndex()] with new backends
8500+
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
8501+
io.KeysDown[key] = keydata->Down;
8502+
if (io.KeyMap[key] != -1)
8503+
io.KeysDown[io.KeyMap[key]] = keydata->Down;
8504+
#endif
84788505
}
84798506
}
84808507
else if (e->Type == ImGuiInputEventType_Text)
84818508
{
84828509
// Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
8483-
if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
8510+
if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
84848511
break;
84858512
unsigned int c = e->Text.Char;
84868513
io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
8487-
text_inputed = true;
8514+
if (trickle_interleaved_keys_and_text)
8515+
text_inputted = true;
84888516
}
84898517
else if (e->Type == ImGuiInputEventType_Focus)
84908518
{
@@ -8503,6 +8531,11 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
85038531
for (int n = 0; n < event_n; n++)
85048532
g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
85058533

8534+
// [DEBUG]
8535+
/*if (event_n != 0)
8536+
for (int n = 0; n < g.InputEventsQueue.Size; n++)
8537+
DebugLogInputEvent(n < event_n ? "Processed" : "Remaining", &g.InputEventsQueue[n]);*/
8538+
85068539
// Remaining events will be processed on the next frame
85078540
if (event_n == g.InputEventsQueue.Size)
85088541
g.InputEventsQueue.resize(0);
@@ -8567,7 +8600,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
85678600
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
85688601
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
85698602
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
8570-
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
8603+
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < ImGuiKey_LegacyNativeKey_END && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
85718604

85728605
// Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
85738606
if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1)

imgui.h

+9-11
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Index of this file:
6565
// Version
6666
// (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)
6767
#define IMGUI_VERSION "1.88 WIP"
68-
#define IMGUI_VERSION_NUM 18707
68+
#define IMGUI_VERSION_NUM 18709
6969
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
7070
#define IMGUI_HAS_TABLE
7171
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
@@ -1484,19 +1484,17 @@ enum ImGuiKey_
14841484
ImGuiKey_GamepadRStickLeft, // [Analog]
14851485
ImGuiKey_GamepadRStickRight, // [Analog]
14861486

1487-
// Keyboard Modifiers
1487+
// Keyboard Modifiers (explicitly submitted by backend via AddKeyEvent() calls)
14881488
// - This is mirroring the data also written to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper, in a format allowing
14891489
// them to be accessed via standard key API, allowing calls such as IsKeyPressed(), IsKeyReleased(), querying duration etc.
14901490
// - Code polling every keys (e.g. an interface to detect a key press for input mapping) might want to ignore those
14911491
// and prefer using the real keys (e.g. ImGuiKey_LeftCtrl, ImGuiKey_RightCtrl instead of ImGuiKey_ModCtrl).
14921492
// - In theory the value of keyboard modifiers should be roughly equivalent to a logical or of the equivalent left/right keys.
14931493
// In practice: it's complicated; mods are often provided from different sources. Keyboard layout, IME, sticky keys and
14941494
// backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user...
1495-
ImGuiKey_ModCtrl,
1496-
ImGuiKey_ModShift,
1497-
ImGuiKey_ModAlt,
1498-
ImGuiKey_ModSuper,
1495+
ImGuiKey_ModCtrl, ImGuiKey_ModShift, ImGuiKey_ModAlt, ImGuiKey_ModSuper,
14991496

1497+
// End of list
15001498
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value
15011499

15021500
// [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + a io.KeyMap[] array.
@@ -1982,13 +1980,13 @@ struct ImGuiKeyData
19821980
struct ImGuiIO
19831981
{
19841982
//------------------------------------------------------------------
1985-
// Configuration (fill once) // Default value
1983+
// Configuration // Default value
19861984
//------------------------------------------------------------------
19871985

19881986
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
19891987
ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
1990-
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size)
1991-
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
1988+
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
1989+
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame.
19921990
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
19931991
const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
19941992
const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
@@ -2099,7 +2097,7 @@ struct ImGuiIO
20992097
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
21002098
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
21012099
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
2102-
bool KeysDown[512]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
2100+
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
21032101
#endif
21042102

21052103
//------------------------------------------------------------------
@@ -2133,7 +2131,7 @@ struct ImGuiIO
21332131
ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
21342132
bool MouseReleased[5]; // Mouse button went from Down to !Down
21352133
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
2136-
bool MouseDownOwnedUnlessPopupClose[5]; //Track if button was clicked inside a dear imgui window.
2134+
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
21372135
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
21382136
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
21392137
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point

imgui_demo.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -5739,12 +5739,18 @@ static void ShowDemoWindowMisc()
57395739
ImGuiIO& io = ImGui::GetIO();
57405740

57415741
// Display ImGuiIO output flags
5742-
ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
5743-
ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
5744-
ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
5745-
ImGui::Text("WantTextInput: %d", io.WantTextInput);
5746-
ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
5747-
ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
5742+
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Output");
5743+
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
5744+
if (ImGui::TreeNode("Output"))
5745+
{
5746+
ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
5747+
ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
5748+
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
5749+
ImGui::Text("io.WantTextInput: %d", io.WantTextInput);
5750+
ImGui::Text("io.WantSetMousePos: %d", io.WantSetMousePos);
5751+
ImGui::Text("io.NavActive: %d, io.NavVisible: %d", io.NavActive, io.NavVisible);
5752+
ImGui::TreePop();
5753+
}
57485754

57495755
// Display Mouse state
57505756
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse State");
@@ -5777,6 +5783,7 @@ static void ShowDemoWindowMisc()
57775783
#else
57785784
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
57795785
const ImGuiKey key_first = 0;
5786+
//ImGui::Text("Legacy raw:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
57805787
#endif
57815788
ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f secs)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } }
57825789
ImGui::Text("Keys pressed:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }

0 commit comments

Comments
 (0)