winmr-api/Utils/Shortcuts.cs
2026-01-08 21:35:06 +03:00

186 lines
6.1 KiB
C#

using Google.Protobuf;
using WebmrAPI.Utils.Sequences;
using WinIPC.Models;
using WinIPC.Utils;
namespace WebmrAPI.Utils
{
public class Key
{
public Button Code { get; private set; }
public Key(Button code) { Code = code; }
public Key(string key)
{
Button code;
switch (key.ToLowerInvariant())
{
case "-": case "_": Code = Button.Sub; break;
case "+": case "=": Code = Button.Add; break;
case "~": case "`": Code = Button.Tilde; break;
case "<": case ",": Code = Button.Comma; break;
case ">": case ".": Code = Button.Period; break;
case ":": case ";": Code = Button.Colon; break;
case "{": case "[": Code = Button.LBracket; break;
case "}": case "]": Code = Button.RBracket; break;
case "\\": case "|": Code = Button.BSol; break;
case "/": case "?": Code = Button.Sol; break;
case "'": case "\"": Code = Button.Quote; break;
case "num+": Code = Button.NumAdd; break;
case "num-": Code = Button.NumSub; break;
case "num*": Code = Button.NumMul; break;
case "num/": Code = Button.NumDiv; break;
case "num.": Code = Button.NumDec; break;
case "a": case "b": case "c": case "d": case "e": case "f":
case "g": case "h": case "i": case "j": case "k": case "l":
case "m": case "n": case "o": case "p": case "q": case "r":
case "s": case "t": case "u": case "v": case "w": case "x":
case "y": case "z": case "0": case "1": case "2": case "3":
case "4": case "5": case "6": case "7": case "8": case "9":
if (Enum.TryParse($"Key{key}", out code))
{
Code = code;
break;
}
else goto default;
case "shift": case "ctrl": case "alt": case "win":
if (Enum.TryParse($"L{key}", out code))
{
Code = code;
break;
}
else goto default;
default:
if (Enum.TryParse(key, out code))
{
Code = code;
break;
}
else throw new ArgumentException($"Unexpected key \"{key}\"");
}
}
}
public class KeyShortcutSequence
{
private Queue<KeyValuePair<KeyShortcut, uint>> _queue = new();
public KeyShortcutSequence(KeyShortcut key) { Next(key); }
public KeyShortcutSequence Next(KeyShortcut shortcut, int delay = 0)
{
_queue.Enqueue(new KeyValuePair<KeyShortcut, uint>(shortcut, (uint)delay));
return this;
}
public IEnumerable<InputAction> GetInputActions()
{
var actions = new InputAction[0];
do
{
var kvpair = _queue.Dequeue();
if (actions.Length > 0)
{
actions[actions.Length - 1].DelayMs += kvpair.Value;
}
actions = actions.Concat(kvpair.Key.GetInputActions()).ToArray();
} while (_queue.Count > 0);
return actions;
}
}
public class KeyShortcut
{
private readonly static DelayGenerator _dGen = new(new PerlinNumberGenerator<int>(75, 200, Int32.MaxValue));
private Queue<Key> _queue = new();
public KeyShortcut(Key key) { And(key); }
public KeyShortcut(string key) { And(key); }
public KeyShortcut And(Key key)
{
_queue.Enqueue(key);
return this;
}
public KeyShortcut And(string key)
{
return And(new Key(key));
}
public IEnumerable<InputAction> GetHoldDownActions()
{
Key key;
var actions = new InputAction[_queue.Count];
for (int i = 0, n = _queue.Count; i < n;)
{
_queue.Enqueue(key = _queue.Dequeue());
actions[i++] = new InputAction()
{
DelayMs = (uint)_dGen.Next().Value,
Type = InputType.KeyDown,
Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code }))
};
}
return actions;
}
public IEnumerable<InputAction> GetHoldUpActions()
{
Key key;
var actions = new InputAction[_queue.Count];
for (int n = _queue.Count; n > 0;)
{
_queue.Enqueue(key = _queue.Dequeue());
actions[--n] = new InputAction()
{
DelayMs = (uint)_dGen.Next().Value,
Type = InputType.KeyUp,
Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code }))
};
}
return actions;
}
public IEnumerable<InputAction> GetInputActions()
{
Key key;
int n = _queue.Count * 2;
var actions = new InputAction[n];
for (int i = 0; i < n;)
{
_queue.Enqueue(key = _queue.Dequeue());
actions[i++] = new InputAction()
{
DelayMs = (uint)_dGen.Next().Value,
Type = InputType.KeyDown,
Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code }))
};
actions[--n] = new InputAction()
{
DelayMs = (uint)_dGen.Next().Value,
Type = InputType.KeyUp,
Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code }))
};
}
return actions;
}
}
}