Keyboard Lock API でキーをキャプチャする

インタラクティブなウェブサイト、ゲーム、リモート デスクトップ、アプリケーション ストリーミングなど、さまざまなユースケースで没入感のある全画面表示エクスペリエンスを提供します。

多くのユーザーがブラウザでほとんどの時間を過ごすようになり、インタラクティブなウェブサイト、ゲーム、リモート デスクトップ ストリーミング、アプリケーション ストリーミングでは、没入感のある全画面表示のエクスペリエンスを提供することが求められています。これを実現するには、サイトが全画面表示モードのときに、ナビゲーション、メニュー、ゲームに使用できる特殊なキーやキーボード ショートカットにアクセスする必要があります。たとえば、Esc、Alt+Tab、Cmd+`、Ctrl+N などのキーが必要になる場合があります。

デフォルトでは、これらのキーはブラウザまたは基盤となるオペレーティング システムによってキャプチャされるため、ウェブ アプリケーションでは使用できません。Keyboard Lock API を使用すると、ウェブサイトはホスト OS で許可されているすべてのキーを使用できます(ブラウザの互換性をご覧ください)。

macOS Chrome のブラウザタブにストリーミングされた Ubuntu Linux(まだ全画面モードでは実行されていません)。
問題: ストリーミングされた Ubuntu Linux リモート デスクトップが全画面モードで実行されておらず、キーボード ロックが有効になっていないため、システムキーが macOS ホスト オペレーティング システムによってキャプチャされ、没入感が得られない。

Keyboard Lock API の使用

Keyboard API の Keyboard インターフェースには、物理キーボードからのキー押下のキャプチャを切り替える関数と、ユーザーのキーボード レイアウトに関する情報を取得する関数が用意されています。

前提条件

最新のブラウザでは、Fullscreen API を介して JavaScript で開始される全画面表示と、キーボード ショートカットを介してユーザーが開始する全画面表示の 2 種類があります。Keyboard Lock API は、JavaScript で開始された全画面表示がアクティブな場合にのみ使用できます。JavaScript で開始される全画面表示の例を次に示します。

await document.documentElement.requestFullscreen();

特徴検出

次のパターンを使用して、Keyboard Lock API がサポートされているかどうかを確認できます。

if ('keyboard' in navigator && 'lock' in navigator.keyboard) {
  // Supported!
}

キーボードをロックする

Keyboard インターフェースの lock() メソッドは、物理キーボードのいずれかまたはすべてのキーの押下のキャプチャを有効にした後、Promise を返します。このメソッドでキャプチャできるのは、基盤となるオペレーティング システムによってアクセスが許可されているキーのみです。lock() メソッドは、ロックする 1 つ以上のキーコードの配列を受け取ります。キーコードが指定されていない場合、すべてのキーがロックされます。有効なキーコード値のリストについては、UI Events KeyboardEvent code Values の仕様をご覧ください。

すべてのキーをキャプチャする

次の例では、すべてのキー押下をキャプチャします。

navigator.keyboard.lock();

特定のキーのキャプチャ

次の例では、W、A、S、D の各キーをキャプチャしています。キーの押下時にどの修飾キーが使用されているかに関係なく、これらのキーをキャプチャします。US QWERTY レイアウトを想定すると、"KeyW" を登録することで、W、Shift+W、Control+W、Control+Shift+W、および W との他のすべてのキー修飾子の組み合わせがアプリに送信されます。"KeyA"、"KeyS"、"KeyD" についても同様です。

await navigator.keyboard.lock([
  "KeyW",
  "KeyA",
  "KeyS",
  "KeyD",
]);

キーボード イベントを使用して、キャプチャされたキーの押下に応答できます。たとえば、次のコードでは onkeydown イベントを使用しています。

document.addEventListener('keydown', (event) => {
  if ((event.code === 'KeyA') && !(event.ctrlKey || event.metaKey)) {
    // Do something when the 'A' key was pressed, but only
    // when not in combination with the command or control key.
  }
});

キーボードのロックを解除する

unlock() メソッドは、lock() メソッドによってキャプチャされたすべてのキーのロックを解除し、同期的に戻ります。

navigator.keyboard.unlock();

ドキュメントが閉じられると、ブラウザは常に暗黙的に unlock() を呼び出します。

デモ

Keyboard Lock API は、こちらのデモを実行してテストできます。ソースコードもぜひご確認ください。下の [全画面表示にする] ボタンをクリックすると、デモが新しいウィンドウで起動し、全画面表示モードに切り替えることができます。

セキュリティ上の考慮事項

この API に関する懸念事項の 1 つは、すべてのキーを取得するために使用され、(Fullscreen API と PointerLock API と組み合わせて)ユーザーがウェブページを終了できなくなる可能性があることです。これを防ぐため、仕様では、API によってすべてのキーがリクエストされた場合でも、ユーザーがキーボード ロックを終了する方法をブラウザが提供することを求めています。Chrome では、このエスケープ ハッチは Esc キーを長押し(2 秒間)してキーボード ロックを終了します。

謝辞

この記事は、Joe Medley と Kayce Basques がレビューしました。Keyboard Lock の仕様は、Gary Kacmarcik 氏と Jamie Walch 氏によって作成されました。