loading
Note:
Not the same as the Keyboard service Butil's Keyboard service registers app-level shortcuts on top of ordinary key events. These two change which keys reach the page at all, and what to call them - which is what a game, a remote-desktop client or a shortcut-hint UI needs.
Warning:
Lock needs fullscreen Keyboard lock requires a secure context, a top-level browsing context and fullscreen. The lock is dropped the moment fullscreen ends, so a user can never be trapped: even with Escape locked, holding it still exits. Chromium desktop only.

Support check

KeyboardLock.IsSupported / KeyboardLayout.IsSupported

The two halves are probed separately. During prerender/SSR both return false rather than throwing, so defer them to OnAfterRenderAsync.

C#
@inject Bit.Butil.KeyboardLock keyboardLock
@inject Bit.Butil.KeyboardLayout keyboardLayout

var canLock = await keyboardLock.IsSupported();
var canReadLayout = await keyboardLayout.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Capture keys while fullscreen

Lock / Unlock

Enter fullscreen first, then lock. Passing no codes captures everything the platform allows; passing codes captures only those. Calling Lock again replaces the previous set rather than adding to it. Leaving fullscreen unlocks on its own, so Unlock is for the case where the page stays fullscreen and simply stops needing the keys.

Razor
@inject Bit.Butil.KeyboardLock keyboardLock

<div @ref="_stage">...</div>
<button @onclick="Enter">Go fullscreen</button>

@code {
    private ElementReference _stage;

    // The lock only holds while the document is fullscreen, so the two go together: leaving
    // fullscreen releases it, and asking for it outside fullscreen does nothing.
    private async Task Enter()
    {
        await _stage.RequestFullScreen(null);

        var locked = await keyboardLock.Lock("Escape", "KeyW", "F11");
    }

    private async Task Leave() => await keyboardLock.Unlock();
}
Live sample
This box goes fullscreen. Lock only works while it is.
keyboard lock output
Results will appear here when you interact with the samples.

Show the right key name

GetLayoutMap / Get

A shortcut is bound to a physical key (KeyboardEvent.code), but the hint shown to the user has to be the character that key produces. Hard-coding 'W' is wrong on AZERTY, where the same key prints 'Z'. Look the code up and show what comes back.

C#
var label = await keyboardLayout.Get("KeyW") ?? "W";
_shortcutHint = $"Ctrl+{label.ToUpperInvariant()}";
Live sample
layout output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
KeyboardLock.IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes navigator.keyboard.lock.
KeyboardLock.Lock
ValueTask<bool> Lock(params string[] codes)
Captures the given physical keys for the page. Pass none to capture everything the platform allows. False when the page isn't fullscreen or the platform refused.
KeyboardLock.Unlock
ValueTask Unlock()
Releases every captured key. Safe to call when nothing is locked.
KeyboardLayout.IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes navigator.keyboard.getLayoutMap.
KeyboardLayout.GetLayoutMap
ValueTask<KeyboardLayoutEntry[]> GetLayoutMap()
Every writing-system key the browser knows about, paired with the character it prints.
KeyboardLayout.Get
ValueTask<string?> Get(string code)
What one physical key prints on this layout. Null when the runtime can't report a layout.
An unhandled error has occurred. Reload 🗙