mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	This commit is contained in:
		| @@ -130,6 +130,7 @@ Other Changes: | ||||
| - IO: Added ImGuiMod_Shortcut which is ImGuiMod_Super on Mac and ImGuiMod_Ctrl otherwise. (#456) | ||||
| - IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey | ||||
|   can apply to mouse data as well. (#4921) | ||||
| - IO: Filter duplicate input events during the AddXXX() calls. (#5599, #4921) | ||||
| - Menus: Fixed incorrect sub-menu parent association when opening a menu by closing another. | ||||
|   Among other things, it would accidentally break part of the closing heuristic logic when moving | ||||
|   towards a sub-menu. (#2517, #5614). [@rokups] | ||||
|   | ||||
							
								
								
									
										68
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -1282,11 +1282,13 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // FIXME: Perhaps we could clear queued events as well? | ||||
| void ImGuiIO::ClearInputCharacters() | ||||
| { | ||||
|     InputQueueCharacters.resize(0); | ||||
| } | ||||
|  | ||||
| // FIXME: Perhaps we could clear queued events as well? | ||||
| void ImGuiIO::ClearInputKeys() | ||||
| { | ||||
| #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
| @@ -1302,6 +1304,23 @@ void ImGuiIO::ClearInputKeys() | ||||
|     KeyMods = ImGuiMod_None; | ||||
| } | ||||
|  | ||||
| static ImGuiInputEvent* FindLatestInputEvent(ImGuiInputEventType type, int arg = -1) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     for (int n = g.InputEventsQueue.Size - 1; n >= 0; n--) | ||||
|     { | ||||
|         ImGuiInputEvent* e = &g.InputEventsQueue[n]; | ||||
|         if (e->Type != type) | ||||
|             continue; | ||||
|         if (type == ImGuiInputEventType_Key && e->Key.Key != arg) | ||||
|             continue; | ||||
|         if (type == ImGuiInputEventType_MouseButton && e->MouseButton.Button != arg) | ||||
|             continue; | ||||
|         return e; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| // Queue a new key down/up event. | ||||
| // - 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. | ||||
| @@ -1327,17 +1346,13 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value) | ||||
|     if (ImGui::IsGamepadKey(key)) | ||||
|         BackendUsingLegacyNavInputArray = false; | ||||
|  | ||||
|     // Partial filter of duplicates (not strictly needed, but makes data neater in particular for key mods and gamepad values which are most commonly spmamed) | ||||
|     ImGuiKeyData* key_data = ImGui::GetKeyData(key); | ||||
|     if (key_data->Down == down && key_data->AnalogValue == analog_value) | ||||
|     { | ||||
|         bool found = false; | ||||
|         for (int n = g.InputEventsQueue.Size - 1; n >= 0 && !found; n--) | ||||
|             if (g.InputEventsQueue[n].Type == ImGuiInputEventType_Key && g.InputEventsQueue[n].Key.Key == key) | ||||
|                 found = true; | ||||
|         if (!found) | ||||
|             return; | ||||
|     } | ||||
|     // Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed) | ||||
|     const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_Key, (int)key); | ||||
|     const ImGuiKeyData* key_data = ImGui::GetKeyData(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) | ||||
|         return; | ||||
|  | ||||
|     // Add event | ||||
|     ImGuiInputEvent e; | ||||
| @@ -1395,11 +1410,20 @@ void ImGuiIO::AddMousePosEvent(float x, float y) | ||||
|     if (!AppAcceptingEvents) | ||||
|         return; | ||||
|  | ||||
|     // Apply same flooring as UpdateMouseInputs() | ||||
|     ImVec2 pos((x > -FLT_MAX) ? ImFloorSigned(x) : x, (y > -FLT_MAX) ? ImFloorSigned(y) : y); | ||||
|  | ||||
|     // Filter duplicate | ||||
|     const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_MousePos); | ||||
|     const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) : g.IO.MousePos; | ||||
|     if (latest_pos.x == pos.x && latest_pos.y == pos.y) | ||||
|         return; | ||||
|  | ||||
|     ImGuiInputEvent e; | ||||
|     e.Type = ImGuiInputEventType_MousePos; | ||||
|     e.Source = ImGuiInputSource_Mouse; | ||||
|     e.MousePos.PosX = x; | ||||
|     e.MousePos.PosY = y; | ||||
|     e.MousePos.PosX = pos.x; | ||||
|     e.MousePos.PosY = pos.y; | ||||
|     g.InputEventsQueue.push_back(e); | ||||
| } | ||||
|  | ||||
| @@ -1411,6 +1435,12 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) | ||||
|     if (!AppAcceptingEvents) | ||||
|         return; | ||||
|  | ||||
|     // Filter duplicate | ||||
|     const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_MouseButton, (int)mouse_button); | ||||
|     const bool latest_button_down = latest_event ? latest_event->MouseButton.Down : g.IO.MouseDown[mouse_button]; | ||||
|     if (latest_button_down == down) | ||||
|         return; | ||||
|  | ||||
|     ImGuiInputEvent e; | ||||
|     e.Type = ImGuiInputEventType_MouseButton; | ||||
|     e.Source = ImGuiInputSource_Mouse; | ||||
| @@ -1424,7 +1454,9 @@ void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
|     if ((wheel_x == 0.0f && wheel_y == 0.0f) || !AppAcceptingEvents) | ||||
|  | ||||
|     // Filter duplicate (unlike most events, wheel values are relative and easy to filter) | ||||
|     if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f)) | ||||
|         return; | ||||
|  | ||||
|     ImGuiInputEvent e; | ||||
| @@ -1440,6 +1472,12 @@ void ImGuiIO::AddFocusEvent(bool focused) | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
|  | ||||
|     // Filter duplicate | ||||
|     const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_Focus); | ||||
|     const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !g.IO.AppFocusLost; | ||||
|     if (latest_focused == focused) | ||||
|         return; | ||||
|  | ||||
|     ImGuiInputEvent e; | ||||
|     e.Type = ImGuiInputEventType_Focus; | ||||
|     e.AppFocused.Focused = focused; | ||||
| @@ -8123,8 +8161,6 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) | ||||
|         { | ||||
|             // Trickling Rule: Stop processing queued events if we already handled a mouse button change | ||||
|             ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY); | ||||
|             if (IsMousePosValid(&event_pos)) | ||||
|                 event_pos = ImVec2(ImFloorSigned(event_pos.x), ImFloorSigned(event_pos.y)); // Apply same flooring as UpdateMouseInputs() | ||||
|             if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted)) | ||||
|                 break; | ||||
|             io.MousePos = event_pos; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user