fix(keyboard-shortcuts) fix PTT on keyboards which send repeated keys

Come over for a fun story, dear reader!

Here is a not-so-fun difference in behavior, observed in macOS:

- The builtin keyboard doesn't seem to send the same key over and over
  again while it's being held.
- On the contrary, a USB keyboard does.

That means that for some keyboards PTT has been broken. We get
keydown/keyup pairs in quick successing.

One would think that KeyboardEvent.repeat would solve that, but it
doesn't seem to, in practice. See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

So, in order to solve this, delay handling the keyup event by 50ms. This
way, if a new keydown comes before the keyup has been handled we'll
cancel it and act as it never happened, restoring PTT functionality.

While we're at it, use window.addEventListener rather than
onkeyup/onkeydown, since it's 2024 :-)
pull/14851/head jitsi-meet_9626
Saúl Ibarra Corretgé 11 months ago committed by Saúl Ibarra Corretgé
parent de1e470c68
commit 74b02af318
  1. 25
      react/features/keyboard-shortcuts/actions.web.ts

@ -41,9 +41,7 @@ const initGlobalKeyboardShortcuts = () =>
helpCharacter: 'SPACE',
helpDescription: 'keyboardShortcuts.pushToTalk',
handler: () => {
sendAnalytics(createShortcutEvent('push.to.talk', ACTION_SHORTCUT_RELEASED));
logger.log('Talk shortcut released');
APP.conference.muteAudio(true);
// Handled directly on the global handler.
}
}));
@ -82,7 +80,10 @@ export const initKeyboardShortcuts = () =>
(dispatch: IStore['dispatch'], getState: IStore['getState']) => {
dispatch(initGlobalKeyboardShortcuts());
window.onkeyup = (e: KeyboardEvent) => {
const pttDelay = 50;
let pttTimeout: number | undefined;
window.addEventListener('keyup', (e: KeyboardEvent) => {
const state = getState();
const enabled = areKeyboardShortcutsEnabled(state);
const shortcuts = getKeyboardShortcuts(state);
@ -93,12 +94,21 @@ export const initKeyboardShortcuts = () =>
const key = getKeyboardKey(e).toUpperCase();
if (key === ' ') {
clearTimeout(pttTimeout);
pttTimeout = window.setTimeout(() => {
sendAnalytics(createShortcutEvent('push.to.talk', ACTION_SHORTCUT_RELEASED));
logger.log('Talk shortcut released');
APP.conference.muteAudio(true);
}, pttDelay);
}
if (shortcuts.has(key)) {
shortcuts.get(key)?.handler(e);
}
};
});
window.onkeydown = (e: KeyboardEvent) => {
window.addEventListener('keydown', (e: KeyboardEvent) => {
const state = getState();
const enabled = areKeyboardShortcutsEnabled(state);
@ -110,11 +120,12 @@ export const initKeyboardShortcuts = () =>
const key = getKeyboardKey(e).toUpperCase();
if (key === ' ' && !focusedElement) {
clearTimeout(pttTimeout);
sendAnalytics(createShortcutEvent('push.to.talk', ACTION_SHORTCUT_PRESSED));
logger.log('Talk shortcut pressed');
APP.conference.muteAudio(false);
} else if (key === 'ESCAPE') {
focusedElement?.blur();
}
};
});
};

Loading…
Cancel
Save