Sokol keyboard event coalescing library.
  • C 66.8%
  • Zig 21.3%
  • Python 5.8%
  • Starlark 4.6%
  • Shell 0.5%
  • Other 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Mikael Säker aaefbf3f79 gitignore: zig-pkg/, the fetched-dependency tree
Every sibling ignores it; sokey was the one that did not, so a fresh
fetch left two package directories showing as untracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 18:10:25 +02:00
src Expose translateLogical for ad-hoc lookups 2026-05-08 23:16:14 +02:00
zig-pkg deps: track sokol e18efdd (reopen-shows-window opt-in) 2026-08-06 01:41:41 +02:00
.gitignore gitignore: zig-pkg/, the fetched-dependency tree 2026-08-07 18:10:25 +02:00
build.zig Initial sokey: sokol keyboard event coalescing with layout-aware logical keys 2026-04-29 07:40:11 +02:00
build.zig.zon deps: track sokol bd6dd7c (reopen request drain) 2026-08-06 10:17:21 +02:00
LICENSE Add MIT license 2026-07-25 12:00:20 +02:00
README.md Initial sokey: sokol keyboard event coalescing with layout-aware logical keys 2026-04-29 07:40:11 +02:00

sokey

Sokol keyboard event coalescing with layout-aware logical keys.

What it does

sokol_app delivers keyboard input as three separate event types (KEY_DOWN, CHAR, KEY_UP). sokey coalesces them into a single KeyEvent per logical press/release that carries:

  • physical — sokol's positional keycode (right answer for arrows, F-keys, modifier-only chords like Cmd+Q)
  • logical — layout-aware unmodified key (right answer for game action bindings and vim-style commands; matches the cap the user sees with the active layout)
  • text — UTF-8 of what the OS would type into a text field (right answer for in-game text input, with shift, dead-keys, IME applied)
  • mods — modifier state at event time
  • kinddown / up / repeat

Both game-style action mapping and text input read from the same stream; each consumer picks the field it needs.

Status

  • macOS: layout-aware via Carbon's TIS / UCKeyTranslate.
  • Windows: stub — logical returns null. Falls back to positional.
  • Linux: stub — same.

Usage

const sapp = @import("sokol").app;
const sokey = @import("sokey");

export fn event(ev_ptr: [*c]const sapp.Event) void {
    sokey.feed(&ev_ptr[0]);
}

fn frame() void {
    sokey.flushPending();
    while (sokey.poll()) |ke| {
        // ke.physical, ke.logical, ke.text(), ke.mods, ke.kind
    }
}

pub fn main() void {
    sokey.disablePressAndHold(); // macOS QoL: hold-to-repeat
    sapp.run(.{ .event_cb = event, .frame_cb = frame,  });
}

Tests

zig build test