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

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

ブラウザを長時間使用するユーザーが増える中、高機能でインタラクティブなウェブサイト、ゲーム、リモート デスクトップ ストリーミング、アプリケーション ストリーミングは、没入感のある全画面表示のエクスペリエンスの提供を目指しています。そのためには、全画面表示モードのときに特別なキーとキーボード ショートカットにアクセスし、ナビゲーション、メニュー、ゲームで使用できるようにする必要があります。必要なキーの例としては、EscAlt+TabCmd+`Ctrl+N などがあります。

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

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

Keyboard Lock API を使用する

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

前提条件

最新のブラウザで利用できる全画面モードは 2 種類あります。Fullscreen API を使用して JavaScript で開始する場合と、ユーザーがキーボード ショートカットで開始する場合です。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 コード値の仕様をご覧ください。

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

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

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

謝辞

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