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;
}
}