diff --git a/src/ChatPrisma/App.xaml.cs b/src/ChatPrisma/App.xaml.cs index 4e11dd9..fd20180 100644 --- a/src/ChatPrisma/App.xaml.cs +++ b/src/ChatPrisma/App.xaml.cs @@ -128,7 +128,7 @@ private IHostBuilder CreateHostBuilder(string[] args) => Microsoft.Extensions.Ho { o.Key = "Y"; o.KeyModifiers = "Ctrl+Shift+Alt"; - o.HotkeyDelayInMilliseconds = 200; + o.HotkeyDelayInMilliseconds = 500; }) .BindConfiguration("Hotkey") .ValidateDataAnnotations() diff --git a/src/ChatPrisma/Services/TextExtractor/ClipboardTextExtractor.cs b/src/ChatPrisma/Services/TextExtractor/ClipboardTextExtractor.cs index d1a1b80..e76a4ca 100644 --- a/src/ChatPrisma/Services/TextExtractor/ClipboardTextExtractor.cs +++ b/src/ChatPrisma/Services/TextExtractor/ClipboardTextExtractor.cs @@ -1,16 +1,18 @@ -using System.Windows.Forms; +using System.Diagnostics; +using System.Windows.Forms; +using System.Windows.Input; using ChatPrisma.Options; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace ChatPrisma.Services.TextExtractor; -public class ClipboardTextExtractor(IOptionsMonitor hotkeyOptions) : ITextExtractor +public class ClipboardTextExtractor(IOptionsMonitor hotkeyOptions, ILogger logger) : ITextExtractor { public async Task GetCurrentTextAsync() { - // Give the user a bit of time to release the keyboard keys, - // otherwise CTRL+C will not work - await Task.Delay(TimeSpan.FromMilliseconds(hotkeyOptions.CurrentValue.HotkeyDelayInMilliseconds)); + // We gotta wait until no keys are pressed anymore, otherwise CTRL+C will not work + await this.WaitUntilNoKeyPressed(); // Need to clear the clipboard, or otherwise we might get some previously copied text Clipboard.Clear(); @@ -23,4 +25,40 @@ public class ClipboardTextExtractor(IOptionsMonitor hotkeyOptions return selectedText; } + + private async Task WaitUntilNoKeyPressed() + { + var task = Task.Delay(TimeSpan.FromMilliseconds(hotkeyOptions.CurrentValue.HotkeyDelayInMilliseconds)); + var watch = Stopwatch.StartNew(); + + // Either wait until the task is completed or the user releases all keys + while (task.IsCompleted is false) + { + if (AnyKeyPressed() is false) + { + logger.LogInformation("Early exit from WaitUntilNoKeyPressed because no key is pressed anymore (after {Time} ms)", watch.Elapsed.TotalMilliseconds); + return; + } + + await Task.Delay(10); + } + + logger.LogInformation("Sadly the user did not release all keys in time (after {Time} ms)", watch.Elapsed.TotalMilliseconds); + } + + private static readonly Key[] s_allKeys = Enum.GetValues(); + private static bool AnyKeyPressed() + { + foreach (var key in s_allKeys) + { + // Skip the None key + if (key == Key.None) + continue; + + if (Keyboard.IsKeyDown(key)) + return true; + } + + return false; + } } diff --git a/src/ChatPrisma/appsettings.json b/src/ChatPrisma/appsettings.json index abf669a..b0dfcf4 100644 --- a/src/ChatPrisma/appsettings.json +++ b/src/ChatPrisma/appsettings.json @@ -10,7 +10,7 @@ "Hotkey": { "Key": "Y", "KeyModifiers": "Ctrl+Shift+Alt", - "HotkeyDelayInMilliseconds": 200, + "HotkeyDelayInMilliseconds": 500, }, "NLog": { "throwConfigExceptions": true,