Last active
October 16, 2023 08:21
-
-
Save t-mat/8771347 to your computer and use it in GitHub Desktop.
Windows: keyrate - keyboard repeat rate configuration utility.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@setlocal enabledelayedexpansion & set "ARGS=%*" & powershell -nop -ex Bypass -c "Add-Type (gc '%~dpf0'|select -Skip 1|Out-String); exit [Program]::Main();" & exit /b !ERRORLEVEL! | |
// How can I increase the key repeat rate beyond the OS's limit? | |
// https://stackoverflow.com/a/11056655 | |
using System; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
public static class Program { | |
[DllImport("shell32.dll")] | |
private static extern IntPtr CommandLineToArgvW( | |
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); | |
[DllImport("kernel32.dll")] | |
private static extern IntPtr LocalFree(IntPtr hMem); | |
private static string[] GetArgs() { | |
string argStr = Environment.GetEnvironmentVariable("ARGS"); | |
if (string.IsNullOrEmpty(argStr)) { | |
return new string[0]; | |
} | |
int nArgs; | |
IntPtr argIntPtrs = CommandLineToArgvW(argStr, out nArgs); | |
if (argIntPtrs == IntPtr.Zero) { | |
return new string[0]; | |
} | |
try { | |
var args = new string[nArgs]; | |
for (int i = 0; i < nArgs; i++) { | |
IntPtr p = Marshal.ReadIntPtr(argIntPtrs, i * IntPtr.Size); | |
args[i] = Marshal.PtrToStringUni(p); | |
} | |
return args; | |
} | |
finally | |
{ | |
LocalFree(argIntPtrs); | |
} | |
} | |
public static int Main() { | |
return KeyRate.Main(GetArgs()); | |
} | |
} | |
public static class KeyRate { | |
[DllImport("user32.dll", SetLastError = false)] | |
internal static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref FILTERKEYS pvParam, uint fWinIni); | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | |
internal struct FILTERKEYS { | |
public uint cbSize; | |
public uint dwFlags; | |
public uint iWaitMSec; | |
public uint iDelayMSec; | |
public uint iRepeatMSec; | |
public uint iBounceMSec; | |
} | |
private const uint SPI_SETFILTERKEYS = 0x0033; | |
private const uint FKF_FILTERKEYSON = 0x0001; | |
private const uint FKF_AVAILABLE = 0x0002; | |
private static void Usage() { | |
Console.WriteLine("Usage: keyrate <delay ms> <repeat ms>"); | |
} | |
public static int Main(string[] args) { | |
if(args.Length != 0 && args.Length != 2) { | |
Usage(); | |
Console.WriteLine("Invoke with no parameters to disable keyrate acceleration."); | |
return 1; // exit code => !ERRORLEVEL! | |
} | |
FILTERKEYS fk; | |
fk.cbSize = 0; | |
fk.dwFlags = 0; | |
fk.iWaitMSec = 0; | |
fk.iDelayMSec = 0; | |
fk.iRepeatMSec = 0; | |
fk.iBounceMSec = 0; | |
if(args.Length == 2) { | |
fk.iDelayMSec = (uint) Math.Max(0, Convert.ToInt32(args[0])); | |
fk.iRepeatMSec = (uint) Math.Max(0, Convert.ToInt32(args[1])); | |
fk.dwFlags = FKF_FILTERKEYSON | FKF_AVAILABLE; | |
Console.WriteLine("Setting keyrate: delay={0}ms, rate={1}ms" | |
, fk.iDelayMSec, fk.iRepeatMSec); | |
} else { | |
Usage(); | |
Console.WriteLine("No parameters given: disabling."); | |
} | |
fk.cbSize = (uint) Marshal.SizeOf(fk); | |
if(! SystemParametersInfo(SPI_SETFILTERKEYS, 0, ref fk, 0)) { | |
Console.WriteLine("System call failed.\nUnable to set keyrate."); | |
return 1; // exit code => !ERRORLEVEL! | |
} | |
return 0; // exit code => !ERRORLEVEL! | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice idea. Here's one that actually works and respects/affects the delay and speed setting that the user can configure in the keyboard UI. https://gist.github.com/ygoe/4c03a9a2b9485356eb56513068607001