Capturar teclas com a API Keyboard Lock

Ofereça uma experiência imersiva em tela cheia para diversos casos de uso, incluindo sites interativos, jogos e streaming remoto de computadores ou aplicativos.

Com cada vez mais usuários passando a maior parte do tempo no navegador, sites extremamente interativos, jogos, streaming de área de trabalho remota e streaming de aplicativos se esforçam para oferecer uma experiência imersiva em tela cheia. Para isso, os sites precisam de acesso a teclas especiais e atalhos de teclado enquanto estão no modo de tela cheia. Assim, eles podem ser usados para navegação, menus ou jogos. São exemplos de teclas necessárias: Esc, Alt + Tab, Cmd + ` e Ctrl + N.

Por padrão, essas chaves não estão disponíveis para o aplicativo da Web porque são capturadas pelo navegador ou pelo sistema operacional subjacente. A API Keyboard Lock permite que os sites usem todas as teclas disponíveis permitidas pelo SO do host. Consulte Compatibilidade do navegador.

O Ubuntu Linux foi transmitido para uma guia do navegador no Chrome para macOS (ainda não está em execução no modo de tela cheia).
O problema: uma área de trabalho remota do Ubuntu Linux com streaming não está sendo executada no modo de tela cheia e sem bloqueio de teclado ativo. Por isso, as chaves do sistema ainda são capturadas pelo sistema operacional do host macOS, e a experiência ainda não é imersiva.

Como usar a API Keyboard Lock

A interface Keyboard da API Keyboard oferece funções que alternam a captura de teclas pressionadas no teclado físico, além de coletar informações sobre o layout do teclado do usuário.

Pré-requisitos

Existem dois tipos de tela cheia disponíveis em navegadores modernos: JavaScript iniciado pela API Fullscreen e iniciado pelo usuário com um atalho de teclado. A API Keyboard Lock só está disponível quando a opção tela cheia iniciada pelo JavaScript está ativa. Veja um exemplo de tela cheia iniciada por JavaScript:

await document.documentElement.requestFullscreen();

Detecção de recursos

Use o seguinte padrão para verificar se há suporte para a API Keyboard Lock:

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

Como bloquear o teclado

O método lock() da interface Keyboard retorna uma promessa depois de ativar a captura de pressionamentos de tecla para qualquer ou todas as teclas do teclado físico. Esse método só captura chaves com acesso concedido pelo sistema operacional subjacente. O método lock() usa uma matriz de um ou mais códigos de teclas para bloquear. Se nenhum código de chave for informado, todas as chaves serão bloqueadas. Uma lista de valores válidos de código de tecla está disponível na especificação Valores de código KeyboardEvent de eventos de interface.

Como capturar todas as chaves

O exemplo a seguir captura todos os pressionamentos de tecla.

navigator.keyboard.lock();

Como capturar chaves específicas

O exemplo a seguir captura as chaves W, A, S e D. Ele captura essas teclas independente dos modificadores usados ao pressionar uma tecla. Considerando um layout QWERTY dos EUA, o registro de "KeyW" garante que W, Shift + W, Control + W, Control + Shift + W e todas as outras combinações do modificador de teclas com W sejam enviadas ao app. O mesmo se aplica a "KeyA", "KeyS" e "KeyD".

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

É possível responder a pressionamentos de tecla capturados usando eventos de teclado. Por exemplo, este código usa o evento 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.
  }
});

Como desbloquear o teclado

O método unlock() desbloqueia todas as chaves capturadas pelo método lock() e retorna de maneira síncrona.

navigator.keyboard.unlock();

Quando um documento é fechado, o navegador sempre chama unlock() implicitamente.

Demonstração

É possível testar a API Keyboard Lock executando a demonstração no Glitch. Não deixe de conferir o código-fonte. Clicar no botão "Entrar em tela cheia" abaixo inicia a demonstração em uma nova janela para entrar no modo de tela cheia.

Considerações sobre segurança

Uma preocupação com essa API é que ela pode ser usada para capturar todas as chaves e, em conjunto com a API Fullscreen e a API PointerLock, impedir o usuário de sair da página da Web. Para evitar isso, a especificação exige que o navegador ofereça uma maneira de o usuário sair do bloqueio de teclado, mesmo que todas as teclas sejam solicitadas pela API. No Chrome, essa saída de emergência é o pressionamento longo (de dois segundos) da tecla Esc para acionar uma saída do bloqueio do teclado.

Agradecimentos

Este artigo foi revisado por Joe Medley e Kayce Basques. A especificação de bloqueio de teclado é de autoria de Gary Kacmarcik e Jamie Walch (links em inglês). Imagem principal de Ken Suarez no Unsplash.