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

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

ユーザーのほとんどがブラウザで時間を過ごすようになり、インタラクティブなウェブサイト、ゲーム、リモート デスクトップ ストリーミング、アプリケーション ストリーミングは、没入感のある全画面エクスペリエンスを提供するようになっています。そのためには、サイトが全画面表示モードのときに特別なキーやキーボード ショートカットにアクセスして、ナビゲーション、メニュー、ゲームに使用できるようにする必要があります。必要なキーの例としては、EscAlt+TabCmd+`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 イベントの KeyboardEvent コード値の仕様をご覧ください。

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

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

navigator.keyboard.lock();

特定のキーをキャプチャする

次の例では、WASD キーをキャプチャします。キー入力に使用された修飾子に関係なく、これらのキーがキャプチャされます。米国の QWERTY レイアウトを前提とすると、"KeyW" を登録すると、WShift+WControl+WControl+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 をテストするには、Glitch でデモを実行します。ソースコードを確認してください。下記の [全画面表示] ボタンをクリックすると、デモが新しいウィンドウで起動され、全画面表示モードになります。

セキュリティに関する考慮事項

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

謝辞

この記事は、Joe MedleyKayce Basques が確認しました。キーボード ロックの仕様は、Gary KacmarcikJamie Walch が作成しました。UnsplashKen Suarez によるヒーロー画像。