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 code Values 仕様で確認できます。

すべてのキーを取得する

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

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 は、このデモを実行してテストできます。ソースコードを必ずご確認ください。下の全画面表示ボタンをクリックすると、デモが新しいウィンドウで起動し、全画面表示モードに切り替わります。

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

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

謝辞

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