feat: initial release of SplitOverlay (KeyOverlay 1.0.0)
CI / build-and-test (push) Canceled after 0s

Semi-transparent always-on-top Windows overlay that shows the keymap of a
Vial/QMK split keyboard (Silakka54).

- draws all layers from a Vial .vil layout, transparent keys fall through
- detects the active layer from the keyboard via a Raw HID command (firmware/)
- shows characters of the active Windows input language
- can split the two halves into separate, independently movable windows
- highlights pressed keys; tray menu for opacity, size and options
- Inno Setup installer and portable build; GitHub-style CI workflow
This commit is contained in:
2026-10-20 09:43:17 +03:00
commit 292d61bb47
48 changed files with 2952 additions and 0 deletions
@@ -0,0 +1,65 @@
using KeyOverlay.Core;
using Xunit;
namespace KeyOverlay.Core.Tests;
public class LayerProtocolTests
{
[Fact]
public void BuildRequest_Is32BytesWithCommandAndVersion()
{
var request = LayerProtocol.BuildRequest();
Assert.Equal(32, request.Length);
Assert.Equal(0xE0, request[0]);
Assert.Equal(0x01, request[1]);
}
[Fact]
public void TryParse_ReadsLayerAndMasks()
{
var payload = new byte[32];
payload[0] = 0xE0;
payload[1] = 0x01;
payload[2] = 2;
payload[3] = 0b0000_0101; // layer_state = layers 0 and 2
payload[7] = 0b0000_0001; // default_layer_state = layer 0
Assert.True(LayerProtocol.TryParse(payload, out var report));
Assert.Equal(2, report.HighestLayer);
Assert.Equal(5u, report.LayerState);
Assert.Equal(1u, report.DefaultLayerState);
}
[Fact]
public void TryParse_ReadsLittleEndianMask()
{
var payload = new byte[32];
payload[0] = 0xE0;
payload[1] = 0x01;
payload[4] = 0x01; // bit 8 of layer_state
Assert.True(LayerProtocol.TryParse(payload, out var report));
Assert.Equal(0x100u, report.LayerState);
}
[Fact]
public void TryParse_RejectsUnhandledResponse()
{
var payload = new byte[32];
payload[0] = 0xFF; // old firmware: "unhandled"
Assert.False(LayerProtocol.TryParse(payload, out _));
}
[Fact]
public void TryParse_RejectsUnknownProtocolVersion()
{
var payload = new byte[32];
payload[0] = 0xE0;
payload[1] = 0x7F;
Assert.False(LayerProtocol.TryParse(payload, out _));
}
[Fact]
public void TryParse_RejectsShortPayload() =>
Assert.False(LayerProtocol.TryParse(new byte[5], out _));
}