From 9ba8f87c814a7caa8bdfed8c77f48070d2533ad0 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sun, 17 Jan 2021 11:51:14 +0100 Subject: [PATCH] Input - Fix keys stuck on Ctrl+Shift+Esc or Ctrl+Alt+Del - closes #509 --- .../Services/Input/InputService.cs | 13 +++++++++- .../Input/Interfaces/IInputService.cs | 5 ++++ ...urrentProcessUtilities.cs => Utilities.cs} | 0 .../NativeWindowInputProvider.cs | 24 ++++++++++++++++++- src/Artemis.UI/Utilities/WindowUtilities.cs | 24 +++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) rename src/Artemis.Core/Utilities/{CurrentProcessUtilities.cs => Utilities.cs} (100%) create mode 100644 src/Artemis.UI/Utilities/WindowUtilities.cs diff --git a/src/Artemis.Core/Services/Input/InputService.cs b/src/Artemis.Core/Services/Input/InputService.cs index 7a03343a3..dff8d7d91 100644 --- a/src/Artemis.Core/Services/Input/InputService.cs +++ b/src/Artemis.Core/Services/Input/InputService.cs @@ -47,7 +47,7 @@ namespace Artemis.Core.Services inputProvider.MouseScrollDataReceived += InputProviderOnMouseScrollDataReceived; inputProvider.MouseMoveDataReceived += InputProviderOnMouseMoveDataReceived; _inputProviders.Add(inputProvider); - + inputProvider.OnKeyboardToggleStatusRequested(); } @@ -296,6 +296,17 @@ namespace Artemis.Core.Services return modifiers; } + public void ReleaseAll() + { + foreach (var (device, keys) in _pressedKeys.ToList()) + { + foreach (KeyboardKey keyboardKey in keys) + { + InputProviderOnKeyboardDataReceived(this, new InputProviderKeyboardEventArgs(device, keyboardKey, false)); + } + } + } + #endregion #region Mouse diff --git a/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs b/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs index 46c042e1f..3c2936354 100644 --- a/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs +++ b/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs @@ -35,6 +35,11 @@ namespace Artemis.Core.Services /// void StopIdentify(); + /// + /// Flush all currently pressed buttons/keys + /// + void ReleaseAll(); + #region Events /// diff --git a/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs b/src/Artemis.Core/Utilities/Utilities.cs similarity index 100% rename from src/Artemis.Core/Utilities/CurrentProcessUtilities.cs rename to src/Artemis.Core/Utilities/Utilities.cs diff --git a/src/Artemis.UI/InputProviders/NativeWindowInputProvider.cs b/src/Artemis.UI/InputProviders/NativeWindowInputProvider.cs index 38da46058..c2dfd8c6c 100644 --- a/src/Artemis.UI/InputProviders/NativeWindowInputProvider.cs +++ b/src/Artemis.UI/InputProviders/NativeWindowInputProvider.cs @@ -1,9 +1,14 @@ using System; +using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; +using System.Timers; using System.Windows.Forms; using System.Windows.Input; +using System.Windows.Interop; using Artemis.Core; using Artemis.Core.Services; +using Artemis.UI.Utilities; using Linearstar.Windows.RawInput; using Linearstar.Windows.RawInput.Native; using Serilog; @@ -14,11 +19,12 @@ namespace Artemis.UI.InputProviders public class NativeWindowInputProvider : InputProvider { private const int WM_INPUT = 0x00FF; + private readonly IInputService _inputService; - private readonly ILogger _logger; private DateTime _lastMouseUpdate; private SpongeWindow _sponge; + private System.Timers.Timer _taskManagerTimer; public NativeWindowInputProvider(ILogger logger, IInputService inputService) { @@ -28,10 +34,15 @@ namespace Artemis.UI.InputProviders _sponge = new SpongeWindow(); _sponge.WndProcCalled += SpongeOnWndProcCalled; + _taskManagerTimer = new System.Timers.Timer(500); + _taskManagerTimer.Elapsed += TaskManagerTimerOnElapsed; + _taskManagerTimer.Start(); + RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, _sponge.Handle); RawInputDevice.RegisterDevice(HidUsageAndPage.Mouse, RawInputDeviceFlags.InputSink, _sponge.Handle); } + #region Overrides of InputProvider /// @@ -51,6 +62,8 @@ namespace Artemis.UI.InputProviders { _sponge?.DestroyHandle(); _sponge = null; + _taskManagerTimer?.Dispose(); + _taskManagerTimer = null; } base.Dispose(disposing); @@ -75,6 +88,15 @@ namespace Artemis.UI.InputProviders } } + private void TaskManagerTimerOnElapsed(object sender, ElapsedEventArgs e) + { + // If task manager has focus then we can't track keys properly, release everything to avoid them getting stuck + // Same goes for Idle which is what you get when you press Ctrl+Alt+Del + Process active = Process.GetProcessById(WindowUtilities.GetActiveProcessId()); + if (active?.ProcessName == "Taskmgr" || active?.ProcessName == "Idle") + _inputService.ReleaseAll(); + } + #region Keyboard private void HandleKeyboardData(RawInputData data, RawInputKeyboardData keyboardData) diff --git a/src/Artemis.UI/Utilities/WindowUtilities.cs b/src/Artemis.UI/Utilities/WindowUtilities.cs new file mode 100644 index 000000000..99409febd --- /dev/null +++ b/src/Artemis.UI/Utilities/WindowUtilities.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Artemis.UI.Utilities +{ + public static class WindowUtilities + { + public static int GetActiveProcessId() + { + // Get foreground window handle + IntPtr hWnd = GetForegroundWindow(); + + GetWindowThreadProcessId(hWnd, out uint processId); + return (int) processId; + } + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + } +} \ No newline at end of file