Как получить ключевые модификаторы в Linux Chrome - PullRequest
2 голосов
/ 07 июля 2019

Как моя программа javascript может определить, какие модификаторы были нажаты вместе с событием keydown в Chrome в Linux?

Я попробовал этот код:

document.addEventListener('keydown', function(e)
{
    console.log("KEY DOWN: key=" + e.key + ", code=" + e.code
           + ", meta=" + e.metaKey + ", alt=" + e.altKey);

    // stop propagation, except don't kill F12.
    if (e.code != 'F12')
    {
        e.preventDefault();  // Windows and Firefox
        e.stopPropagation();
        return false;
    } // else: if propagating: Windows wants undefined result.
});

И, пока он работает в Firefox:

// output when I type M-q A-q in Firefox Quantum 67.0.4 (64-bit)
KEY DOWN: key=Meta, code=OSLeft, meta=true, alt=false
KEY DOWN: key=q, code=KeyQ, meta=true, alt=false
KEY DOWN: key=Alt, code=AltLeft, meta=false, alt=true
KEY DOWN: key=q, code=KeyQ, meta=false, alt=true

Linux Chrome, похоже, требует модификатора:

// output when I type M-q A-q in Linux Chrome Version 66.0.3359.181 (Official Build) (64-bit)
KEY DOWN: key=Meta, code=MetaLeft, meta=false, alt=true
KEY DOWN: key=q, code=KeyQ, meta=false, alt=true
KEY DOWN: key=Alt, code=AltLeft, meta=false, alt=true
KEY DOWN: key=q, code=KeyQ, meta=false, alt=false

Очевидно, поля metaKey и altKey поля KeyboardEvent не являются кросс-браузерными. Или я не включил функцию Chrome «клавиши-модификаторы» (как мне это сделать?). Или что-то.

Приведенный выше код прекрасно работает как в Edge, так и в Chrome в Windows. (Windows поймает ключ Windows, если это единственный модификатор, но ваше приложение может отлично ловить комбинации, такие как Ctrl-Meta-x). Например, приведенный выше код имеет одинаковый вывод как в Edge, так и в Chrome в Windows, когда я набираю C-S-M-Q A-Q:

KEY DOWN: key=Control, code=ControlLeft, meta=false, alt=false
KEY DOWN: key=Shift, code=ShiftLeft, meta=false, alt=false
KEY DOWN: key=Meta, code=MetaLeft, meta=true, alt=false
KEY DOWN: key=Q, code=KeyQ, meta=true, alt=false
KEY DOWN: key=Alt, code=AltLeft, meta=false, alt=true
KEY DOWN: key=q, code=KeyQ, meta=false, alt=true

(обратите внимание на одно небольшое различие между Chrome и Edge: Edge имеет code=undefined. Однако в KeyboardEvent все еще достаточно информации, чтобы определить, какая клавиша была нажата, за исключением того, что, возможно, Windows имеет некоторую проблему с сочетанием NumLock + Shift + Keypad номер).

В последний раз, когда я использовал Mac, он поддерживал клавиши Meta и Alt, поэтому вопрос, вероятно, относится и к Mac.

В Linux убедитесь, что на вашем компьютере работают мета-и Alt-ключи, так как некоторые популярные дистрибутивы выходят из коробки. Если он настроен правильно, xmodmap должен сказать:

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Meta_L (0x85),  Meta_R (0x86)
mod2        Num_Lock (0x4d)
mod3        Alt_L (0x40),  Alt_R (0x6c)
mod4      
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

потому что программы интерпретируют mod1 как Meta и mod3 как Alt. (Используйте утилиту xev, чтобы получить коды клавиш для вашей клавиатуры.) С настройками, как показано выше, Firefox, Emacs и другие программы могут правильно перехватывать все клавиши-модификаторы.

Как правильно определить модификаторы, которые были нажаты вместе с событием keydown в Linux Chrome?

Ответы [ 2 ]

2 голосов
/ 08 июля 2019

Я придумал что-то, что работает последовательно в Chrome / Firefox / Edge:

let modifier_challenged = /Google/.test(navigator.vendor);
let last_mod            = {Meta: false, Alt: false};

function keydown(e)
{
if (modifier_challenged)
{
    last_mod[e.key] = true;
    e = {key:      e.key,
         code:     e.code,
         shiftKey: e.shiftKey,
         ctrlKey:  e.ctrlKey};
    e.metaKey = last_mod['Meta'];
    e.altKey  = last_mod['Alt'];
}
console.log("KEY DOWN: key=" + e.key + ", code=" + e.code
        + ", meta=" + e.metaKey + ", alt=" + e.altKey);
}
function keyup(e)
{
if (modifier_challenged)
    last_mod[e.key] = false;
}

document.addEventListener('keydown', keydown);
document.addEventListener('keyup',   keyup);

Но я бы предпочел ответ, который также работает, если модификатор был последний раз нажат или отпущен вне окна (до того, как фокус клавиатуры был перемещен обратно в окно). Может быть, не возможно?

Обновление

Хорошо, приведенный выше код подходит, если вы используете только один модификатор за раз. Но если вы хотите объединить много модификаторов, Chrome все еще имеет проблему ... Он меняет значение key с Alt на Meta, если вы также удерживаете клавишу Shift. Поэтому мы должны использовать:

let modif_codes = /^Control|^Shift|^Meta|^Alt|^OS/;

function set_last_mod(e, value)
{
if (!modif_codes.test(e.key))
    return;
let key_sym = e.code.replace(/([A-Z])/g, " $1").split(" ")[1];
if (key_sym != e.key)
{
    console.log("Warning: code(" + e.code
        + ") does not match key(" + e.key
        + "). Using " + key_sym + ".");
}
last_mod[key_sym] = value;
}

вместо last_mod[e.key] = value.

1 голос
/ 07 июля 2019

Я думаю, что лучший метод для события клавиатуры - KeyboardEvent.getModifierState() Метод KeyboardEvent.getModifierState () возвращает текущее состояние указанной клавиши-модификатора: true, если модификатор активен.

  • Как минимумНачиная с Firefox 48, ключ Windows не считается мета-ключом.KeyboardEvent.metaKey имеет значение false при нажатии ⊞ Windows.

ref: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState

Кроме того, я всегда проверяю user-agent, затем отправляю уведомление для пользователя, котороеКлюч пригоден для использования.

...