diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 535679d63..9fdf31866 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -39,11 +39,11 @@ END TEMPLATE--> ### New features -*None yet* +* Added `BoundKeyEventArgs.IsRepeat`. ### Bugfixes -*None yet* +* Fix assert trip when holding repeatable keybinds. ### Other diff --git a/Robust.Client/Input/InputManager.cs b/Robust.Client/Input/InputManager.cs index a9641d594..4f7d8e8e8 100644 --- a/Robust.Client/Input/InputManager.cs +++ b/Robust.Client/Input/InputManager.cs @@ -346,7 +346,7 @@ namespace Robust.Client.Input { if (binding.CanRepeat) { - return SetBindState(binding, BoundKeyState.Down, uiOnly); + return SetBindState(binding, BoundKeyState.Down, uiOnly, isRepeat); } return true; @@ -375,7 +375,7 @@ namespace Robust.Client.Input SetBindState(binding, BoundKeyState.Up); } - private bool SetBindState(KeyBinding binding, BoundKeyState state, bool uiOnly = false) + private bool SetBindState(KeyBinding binding, BoundKeyState state, bool uiOnly = false, bool isRepeat = false) { if (binding.BindingType == KeyBindingType.Command && state == BoundKeyState.Down) { @@ -387,6 +387,7 @@ namespace Robust.Client.Input // I honestly have no idea what the best solution here is. // note from the future: context switches won't cause re-entrancy anymore because InputContextContainer defers context switches DebugTools.Assert(!_currentlyFindingViewport, "Re-entrant key events??"); + DebugTools.Assert(!isRepeat || binding.CanRepeat); try { @@ -399,7 +400,7 @@ namespace Robust.Client.Input binding.State = state; var eventArgs = new BoundKeyEventArgs(binding.Function, binding.State, - MouseScreenPosition, binding.CanFocus); + MouseScreenPosition, binding.CanFocus, isRepeat); // UI returns true here into blockPass if it wants to prevent us from giving input events // to the viewport, but doesn't want it hard-handled so we keep processing possible key actions. diff --git a/Robust.Client/UserInterface/UserInterfaceManager.Input.cs b/Robust.Client/UserInterface/UserInterfaceManager.Input.cs index 3df130bb3..a82b4c2a1 100644 --- a/Robust.Client/UserInterface/UserInterfaceManager.Input.cs +++ b/Robust.Client/UserInterface/UserInterfaceManager.Input.cs @@ -114,8 +114,10 @@ internal partial class UserInterfaceManager args.Handle(); } - // Attempt to ensure that keybind-up events only get raised after a single keybind-down. - DebugTools.Assert(!_focusedControls.ContainsKey(args.Function)); + // Attempt to ensure that keybind-up events get raised after a keybind-down. + DebugTools.Assert(!_focusedControls.TryGetValue(args.Function, out var existing) + || !existing.VisibleInTree + || args.IsRepeat && existing == control); _focusedControls[args.Function] = control; OnKeyBindDown?.Invoke(control); @@ -124,7 +126,7 @@ internal partial class UserInterfaceManager public void KeyBindUp(BoundKeyEventArgs args) { // Only raise keybind-up for the control on which we previously raised keybind-down - if (!_focusedControls.Remove(args.Function, out var control) || control.Disposed) + if (!_focusedControls.Remove(args.Function, out var control) || !control.VisibleInTree) return; var guiArgs = new GUIBoundKeyEventArgs(args.Function, args.State, args.PointerLocation, args.CanFocus, diff --git a/Robust.Shared/Input/BoundKeyEventArgs.cs b/Robust.Shared/Input/BoundKeyEventArgs.cs index 555cc453c..cf6a0cb86 100644 --- a/Robust.Shared/Input/BoundKeyEventArgs.cs +++ b/Robust.Shared/Input/BoundKeyEventArgs.cs @@ -33,6 +33,11 @@ namespace Robust.Shared.Input public bool Handled { get; private set; } + /// + /// Is this a repeated keypress (i.e., are they holding down the key)? + /// + public readonly bool IsRepeat; + /// /// Constructs a new instance of . /// @@ -47,6 +52,23 @@ namespace Robust.Shared.Input CanFocus = canFocus; } + /// + /// Constructs a new instance of . + /// + /// Bound key that that is changing. + /// New state of the function. + /// Current Pointer location in screen coordinates. + /// + public BoundKeyEventArgs( + BoundKeyFunction function, + BoundKeyState state, + ScreenCoordinates pointerLocation, + bool canFocus, + bool isRepeat = false) : this(function, state, pointerLocation, canFocus) + { + IsRepeat = isRepeat; + } + /// /// Mark this event as handled. ///