Native Windows keyboard layouts ported from Linux xkeyboard-config.
The target is broad xkeyboard-config coverage: Linux keyboard layouts packaged
as Windows kbd*.dll files, not background remappers, so selected layouts can
be registered as normal Windows keyboard layouts and selected with Win+Space.
Windows keyboard layouts are DLLs loaded by the window manager. Microsoft
documents the model in the Windows Driver Samples: a layout DLL contains
scan-code to virtual-key tables plus virtual-key to character tables, and
exports KbdLayerDescriptor.
Windows discovers installed layouts from:
HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\<KLID>
with values such as Layout File and Layout Text. The installer in this
repo registers the selected layout DLLs there, adds them to the current user's
language/input list, and calls LoadKeyboardLayoutW.
MSKLC's GUI and generated installer are not the dependable part of the stack,
especially on Windows 11 ARM64. This repo only uses MSKLC's kbdutool.exe to
convert a .klc source file into C tables, then builds those tables with a
modern compiler.
data\layouts.json is the installable-layout manifest. The installer also
shows the broader Linux/Windows candidate catalog generated from
xkeyboard-config, including layouts not built yet.
The packaged set currently covers the Dvorak-family XKB variants whose Windows
language family exists locally but whose layout variant is not covered by a
Windows built-in. The generated manifest is data\layouts.json.
is-dvorak remains the hand-verified reference layout. src\kbdisdv.klc is
its source of truth. It is a Windows KLC port of xkeyboard-config is(dvorak):
- base:
us(dvorak) - overlay:
eurosign(4) - AltGr:
level3(ralt_switch) - overrides:
„ “ ð Ð æ Æ ö Ö þ Þ ß ẞ – — €
The US Dvorak dead keys inherited by xkeyboard-config are represented as
Windows DEADKEY tables.
Prerequisites:
- Microsoft Keyboard Layout Creator 1.4, for
kbdutool.exe - Visual Studio 2022 Build Tools with Desktop C++
- Windows 10/11 SDK, for
kbd.h - For ARM64 output:
MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools
Build:
.\tools\update-layout-manifest.ps1
.\scripts\build.ps1 -Arch x64
.\scripts\build.ps1 -Arch arm64
.\scripts\build-arm64x-forwarder.ps1
.\scripts\build-installer.ps1Output:
build\<arch>\<layout>.dll
build\arm64x\<layout>.dll
installer\Output\keyremap-setup.exe
The build script verifies the PE machine type and KbdLayerDescriptor export.
It also checks that VsDevCmd selected the requested compiler architecture;
this catches the common ARM64 failure where Visual Studio silently leaves
cl.exe pointed at x64.
For a visible setup wizard, build and run the installer:
.\scripts\build-installer.ps1
.\installer\Output\keyremap-setup.exeThe installer requests elevation, copies the architecture-matched DLL, registers the keyboard layout, and adds an uninstaller entry in Windows.
For script-based local development, open PowerShell as Administrator:
.\scripts\install.ps1With no layout IDs, the script installs every packaged layout in
data\layouts.json. To install one or more specific layouts:
.\scripts\install.ps1 -LayoutId is-dvorak,dk-dvorakUninstall:
.\scripts\uninstall.ps1After installing on the Windows 11 ARM64 laptop, test:
Win+SpaceshowsIcelandic Dvorak- Notepad: base Dvorak keys and AltGr Icelandic letters
- Start search and Settings search
- Microsoft Store or another WinUI/UWP text field
- elevated prompt text entry
- sign-out/sign-in persistence
Render the installed layout through Windows' live translation APIs:
.\tests\render-live-layout.ps1 -Klid 0000040f -ExpectedLayoutName "Icelandic Dvorak" -AssertIcelandicDvorak -HtmlPath .\artifacts\is-dvorak-live.htmlThis calls MapVirtualKeyEx and ToUnicodeEx for the registered layout, so it
checks the same key translation path applications use. It also resolves the
registered display name through Windows' registry string indirection. The HTML
output shows normal, Shift, AltGr, and Shift+AltGr for each physical key.
- xkeyboard-config
symbols/is, variantdvorak - xkeyboard-config
symbols/us, variantdvorak - Microsoft Keyboard Layout Samples
- Microsoft Keyboard Identifiers documentation
- Microsoft
LoadKeyboardLayoutdocumentation
See docs/research.md for the investigation notes.
The repo includes a review pipeline for broader xkeyboard-config coverage:
.\tools\generate-layout-catalog.ps1It parses xkeyboard-config metadata, compares it with the local Windows keyboard registry, and writes:
data\windows-keyboards.local.jsondata\xkb-windows-candidates.jsondocs\layout-candidates.md
This is intentionally review-first. Many XKB entries depend on Compose, IME-like behavior, higher-level groups, or hardware assumptions that are not safe to auto-ship as KLC DLLs without inspection.
The GUI installer displays this catalog. Layouts marked [ready] have packaged
DLLs and can be selected for installation. Layouts marked [not built yet] are
visible so the full Linux target set is clear, but they are disabled until the
generator/build pipeline has produced verified DLLs for them.
The current packaging rule is implemented in
tools\update-layout-manifest.ps1: stable IDs come from xkb layout + variant,
DLL names are stable kx<sha1-prefix>.dll names with <=8-character stems, and
only verified Dvorak-family gaps are marked installable by default. Use
-AllMissing to draft a manifest for every candidate missing variant; those
entries still need converter/build/render review before shipping.
On Windows 11 ARM, the build produces an ARM64X forwarder plus ARM64 and x64
sidecar DLLs. Current Windows 11 ARM builds can LoadLibrary the pure ARM64X
forwarder, but LoadKeyboardLayout rejects it as the active keyboard layout
file. The installer therefore registers the x64-compatible sidecar as the
visible Layout File and still copies the ARM64/ARM64X companions beside it.
Windows shell text fields do not always honor custom keyboard-layout variants the same way classic desktop apps do. To make those fields use the generated layout, the installer promotes a selected layout to the visible base KLID for that language when it is the only selected packaged layout for that LANGID. If multiple selected layouts target the same LANGID, they remain custom variants unless the manifest explicitly marks one as the base override.