Saltar al contenido

Chrome puede omitir el evento de pérdida de foco en macOS

Un evento de foco avisa a mi medidor de tiempo de que algo pudo cambiar. Antes de registrar un minuto, consulta a Chrome qué ventana tiene el foco.

Extensiones de Chrome2 min de lectura

Ingeniero de software. Desarrollo extensiones de Chrome, aplicaciones web y herramientas de IA aplicada.

Contenido

Amethyst cuenta el tiempo que pasas activamente en cada sitio web. El tiempo solo cuenta mientras la pestaña está visible y una ventana de Chrome tiene el foco. Si cambias a Slack, el reloj de ese sitio debería detenerse.

El evento que no siempre llega

Chrome informa de los cambios de foco mediante chrome.windows.onFocusChanged. Cuando ninguna ventana de Chrome conserva el foco, dispara el evento con chrome.windows.WINDOW_ID_NONE, cuyo valor es -1. Amethyst pausa la sesión cuando lo recibe.

En macOS, ese evento no siempre llega. Puedes cambiar de aplicación con Cmd+Tab o desde el Dock y Chrome pierde el foco sin avisar a las extensiones. La sesión sigue activa, y el sitio que dejaste atrás suma un minuto más, cada minuto, hasta que ocurre otra cosa en Chrome.

Consulta a Chrome antes de guardar

Amethyst guarda el tiempo una vez por minuto mediante una alarma de chrome.alarms. Antes de escribir nada, consulta a Chrome qué ventana tiene el foco, en vez de confiar en el último evento:

const lastFocusedWindow = await windows.getLastFocused();
const focusedWindowId =
  lastFocusedWindow?.focused && typeof lastFocusedWindow.id === 'number'
    ? lastFocusedWindow.id
    : windows.WINDOW_ID_NONE;

getLastFocused() devuelve una ventana aunque Chrome esté en segundo plano. Su propiedad focused indica si Chrome tiene el foco en ese momento. Si es falsa, Amethyst lo trata como un evento de pérdida de foco y pausa la sesión. Al guardar, encuentra una sesión pausada y no escribe nada.

La misma comprobación se ejecuta al cambiar de pestaña, cerrar pestañas y arrancar el worker. El propio manejador de onFocusChanged ignora el identificador de ventana que recibe y vuelve a consultar. El evento solo le dice a Amethyst que algo pudo haber cambiado.

Qué error prefiero

Cuando la comprobación detecta que se perdió el foco, no puede saber cuándo te fuiste. Pudo ser hace dos segundos o hace cincuenta. Por eso, Amethyst termina la sesión en el último instante del que tiene constancia, su lastEventAt, y descarta el tiempo posterior.

Ahora, un evento perdido cuesta un poco de tiempo real. Antes, añadía tiempo que nunca pasaste en el sitio. Prefiero que un medidor cuente unos segundos de menos a que te diga que pasaste la tarde en un sitio que ni siquiera estabas mirando.

Si tu extensión mide el foco, trata onFocusChanged como una pista. Antes de registrar algo que dependa del foco, vuelve a consultar chrome.windows.getLastFocused().

Un pequeño voto de confianza

¿Valió la pena leer esta nota?