[![Crates.io](https://img.shields.io/crates/v/sdl2-keyboard-types.svg)](https://crates.io/crates/sdl2-keyboard-types)
[![Downloads](https://img.shields.io/crates/d/sdl2-keyboard-types.svg)](https://crates.io/crates/sdl2-keyboard-types)
[![Docs.rs](https://docs.rs/sdl2-keyboard-types/badge.svg)](https://docs.rs/sdl2-keyboard-types)
[![Dependencies](https://deps.rs/repo/github/mxmgorin/sdl2-keyboard-types/status.svg)](https://deps.rs/repo/github/mxmgorin/sdl2-keyboard-types)

# sdl2-keyboard-types

A lightweight crate that translates [rust-sdl2](https://github.com/Rust-SDL2/rust-sdl2)
keyboard input into the standardized [keyboard-types](https://github.com/rust-windowing/keyboard-types)
representation used by Servo, druid, blitz, and other Rust UI projects.

It is pure glue: three functions, no runtime state, no allocations beyond the
`Key::Character` strings that `keyboard-types` itself requires.

| Function          | SDL2 input        | `keyboard-types` output | Meaning                          |
| ----------------- | ----------------- | ----------------------- | -------------------------------- |
| `into_code`       | [`Scancode`]      | [`Code`]                | Physical key position (layout-independent) |
| `into_key`        | [`Keycode`]       | [`Key`]                 | Logical key value                |
| `into_modifiers`  | [`Mod`]           | [`Modifiers`]           | Active modifier flags            |

[`Scancode`]: https://docs.rs/sdl2/latest/sdl2/keyboard/enum.Scancode.html
[`Keycode`]: https://docs.rs/sdl2/latest/sdl2/keyboard/enum.Keycode.html
[`Mod`]: https://docs.rs/sdl2/latest/sdl2/keyboard/struct.Mod.html
[`Code`]: https://docs.rs/keyboard-types/latest/keyboard_types/enum.Code.html
[`Key`]: https://docs.rs/keyboard-types/latest/keyboard_types/enum.Key.html
[`Modifiers`]: https://docs.rs/keyboard-types/latest/keyboard_types/struct.Modifiers.html

## Installation

```toml
[dependencies]
sdl2-keyboard-types = "0.1"
```

Both `sdl2` and `keyboard_types` are re-exported from the crate root, so you can
depend on this crate alone and still name their types without adding them to your
own `Cargo.toml`:

```rust
use sdl2_keyboard_types::{sdl2, keyboard_types};
```

All of `rust-sdl2`'s build features (`bundled`, `static-link`, `image`, `ttf`, …)
are forwarded, so enable them here exactly as you would on `sdl2` directly.

## Usage

Assemble a [`keyboard_types::KeyboardEvent`] from an SDL2 event inside your poll loop:

```rust,no_run
use sdl2_keyboard_types::{into_code, into_key, into_modifiers};
use sdl2_keyboard_types::keyboard_types::{KeyState, KeyboardEvent, Location};
use sdl2_keyboard_types::sdl2::event::Event;

fn main() -> Result<(), String> {
    let sdl = sdl2::init()?;
    let video = sdl.video()?;
    let _window = video.window("demo", 640, 480).build().map_err(|e| e.to_string())?;
    let mut events = sdl.event_pump()?;

    'running: loop {
        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode, scancode, keymod, repeat, .. } => {
                    let event = KeyboardEvent {
                        state: KeyState::Down,
                        key: keycode.map(into_key).unwrap_or_default(),
                        code: scancode.map(into_code).unwrap_or_default(),
                        location: Location::Standard,
                        modifiers: into_modifiers(keymod),
                        repeat,
                        is_composing: false,
                    };
                    println!("{event:?}");
                }
                _ => {}
            }
        }
    }
    Ok(())
}
```

## Text input

`into_key` returns **bare, lowercase** `Key::Character` values (`a`, `1`, `-`)
and does **not** apply Shift or any other modifier — `Shift` + `a` still maps to
`"a"`, not `"A"`. This is intentional: a single keycode does not carry layout,
modifier, or IME state.

For actual typed text — uppercase letters, symbols, dead keys, and composed
(IME) input — use SDL2's text-input events (`Event::TextInput`) rather than
deriving characters from this mapping.

## Unmapped keys

Keys without a `keyboard-types` equivalent never panic:

- `into_code` returns [`Code::Unidentified`]
- `into_key` returns `Key::Named(`[`NamedKey::Unidentified`]`)`

[`keyboard_types::KeyboardEvent`]: https://docs.rs/keyboard-types/latest/keyboard_types/struct.KeyboardEvent.html
[`Code::Unidentified`]: https://docs.rs/keyboard-types/latest/keyboard_types/enum.Code.html
[`NamedKey::Unidentified`]: https://docs.rs/keyboard-types/latest/keyboard_types/enum.NamedKey.html

## License

Licensed under the [MIT license](LICENSE).
