mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	Shortcut: do not return true on mods changes. Internals: added ImGuiInputFlags_RepeatUntilKeyModsChange, ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone, ImGuiInputFlags_RepeatUntilOtherKeyPress. (#456, #2637)
Took a while to come to this design, but it is flexible and lightweight and allow all decision to be taken a polling location. All three policies are useful.
This commit is contained in:
		
							
								
								
									
										33
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -8425,7 +8425,7 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
 | 
			
		||||
    if (t < 0.0f)
 | 
			
		||||
        return false;
 | 
			
		||||
    IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function!
 | 
			
		||||
    if (flags & ImGuiInputFlags_RepeatRateMask_) // Setting any _RepeatXXX option enables _Repeat
 | 
			
		||||
    if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_)) // Setting any _RepeatXXX option enables _Repeat
 | 
			
		||||
        flags |= ImGuiInputFlags_Repeat;
 | 
			
		||||
 | 
			
		||||
    bool pressed = (t == 0.0f);
 | 
			
		||||
@@ -8434,6 +8434,19 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
 | 
			
		||||
        float repeat_delay, repeat_rate;
 | 
			
		||||
        GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
 | 
			
		||||
        pressed = (t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
 | 
			
		||||
        if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_))
 | 
			
		||||
        {
 | 
			
		||||
            // Slightly bias 'key_pressed_time' as DownDuration is an accumulation of DeltaTime which we compare to an absolute time value.
 | 
			
		||||
            // Ideally we'd replace DownDuration with KeyPressedTime but it would break user's code.
 | 
			
		||||
            ImGuiContext& g = *GImGui;
 | 
			
		||||
            double key_pressed_time = g.Time - t + 0.00001f;
 | 
			
		||||
            if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (g.LastKeyModsChangeTime > key_pressed_time))
 | 
			
		||||
                pressed = false;
 | 
			
		||||
            if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (g.LastKeyModsChangeFromNoneTime > key_pressed_time))
 | 
			
		||||
                pressed = false;
 | 
			
		||||
            if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (g.LastKeyboardKeyPressTime > key_pressed_time))
 | 
			
		||||
                pressed = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!pressed)
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -8760,11 +8773,16 @@ static void ImGui::UpdateKeyboardInputs()
 | 
			
		||||
    // - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) ->                                      -> (here) deriving io.KeyMods + io.KeyXXX from key array.
 | 
			
		||||
    // - Legacy backends:      set io.KeyXXX bools               -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array.
 | 
			
		||||
    // So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing.
 | 
			
		||||
    const ImGuiKeyChord prev_key_mods = io.KeyMods;
 | 
			
		||||
    io.KeyMods = GetMergedModsFromKeys();
 | 
			
		||||
    io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0;
 | 
			
		||||
    io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0;
 | 
			
		||||
    io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0;
 | 
			
		||||
    io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0;
 | 
			
		||||
    if (prev_key_mods != io.KeyMods)
 | 
			
		||||
        g.LastKeyModsChangeTime = g.Time;
 | 
			
		||||
    if (prev_key_mods != io.KeyMods && prev_key_mods == 0)
 | 
			
		||||
        g.LastKeyModsChangeFromNoneTime = g.Time;
 | 
			
		||||
 | 
			
		||||
    // Clear gamepad data if disabled
 | 
			
		||||
    if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
 | 
			
		||||
@@ -8780,6 +8798,14 @@ static void ImGui::UpdateKeyboardInputs()
 | 
			
		||||
        ImGuiKeyData* key_data = &io.KeysData[i];
 | 
			
		||||
        key_data->DownDurationPrev = key_data->DownDuration;
 | 
			
		||||
        key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
 | 
			
		||||
        if (key_data->DownDuration == 0.0f)
 | 
			
		||||
        {
 | 
			
		||||
            ImGuiKey key = (ImGuiKey)(ImGuiKey_NamedKey_BEGIN + i);
 | 
			
		||||
            if (IsKeyboardKey(key))
 | 
			
		||||
                g.LastKeyboardKeyPressTime = g.Time;
 | 
			
		||||
            else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
 | 
			
		||||
                g.LastKeyboardKeyPressTime = g.Time;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update keys/input owner (named keys only): one entry per key
 | 
			
		||||
@@ -9315,6 +9341,11 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
 | 
			
		||||
    if (!SetShortcutRouting(key_chord, owner_id, flags))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // Default repeat behavior for Shortcut()
 | 
			
		||||
    // So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut.
 | 
			
		||||
    if ((flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
 | 
			
		||||
        flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
 | 
			
		||||
 | 
			
		||||
    if (!IsKeyChordPressed(key_chord, owner_id, flags))
 | 
			
		||||
        return false;
 | 
			
		||||
    IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function!
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user