using System; using AcDream.UI.Abstractions.Input; using Silk.NET.Input; namespace AcDream.App.Input; /// /// Bridges a Silk.NET to the test-fakeable /// interface used by /// . K.1a wiring: GameWindow constructs /// one of these wrapping the first keyboard from /// IInputContext.Keyboards; the dispatcher fans events out to /// subscribers without ever touching Silk types directly. /// public sealed class SilkKeyboardSource : IKeyboardSource { private readonly IKeyboard _keyboard; public event Action? KeyDown; public event Action? KeyUp; public SilkKeyboardSource(IKeyboard keyboard) { _keyboard = keyboard ?? throw new ArgumentNullException(nameof(keyboard)); _keyboard.KeyDown += (_, key, _) => KeyDown?.Invoke(key, ReadModifiers()); _keyboard.KeyUp += (_, key, _) => KeyUp?.Invoke(key, ReadModifiers()); } public bool IsHeld(Key key) => _keyboard.IsKeyPressed(key); public ModifierMask CurrentModifiers => ReadModifiers(); private ModifierMask ReadModifiers() { ModifierMask m = ModifierMask.None; if (_keyboard.IsKeyPressed(Key.ShiftLeft) || _keyboard.IsKeyPressed(Key.ShiftRight)) m |= ModifierMask.Shift; if (_keyboard.IsKeyPressed(Key.ControlLeft) || _keyboard.IsKeyPressed(Key.ControlRight)) m |= ModifierMask.Ctrl; if (_keyboard.IsKeyPressed(Key.AltLeft) || _keyboard.IsKeyPressed(Key.AltRight)) m |= ModifierMask.Alt; if (_keyboard.IsKeyPressed(Key.SuperLeft) || _keyboard.IsKeyPressed(Key.SuperRight)) m |= ModifierMask.Win; return m; } }