【问题标题】:How to get key modifiers in Linux Chrome如何在 Linux Chrome 中获取键修饰符
【发布时间】:2019-07-07 16:57:27
【问题描述】:

我的 javascript 程序如何确定在 Linux 上的 Chrome 中按下了哪些修饰符以及 keydown 事件?

我试过这段代码:

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

显然,KeyboardEventmetaKeyaltKey 字段不是跨浏览器的。或者我没有打开 Chrome 的“修改键”功能(我该怎么做?)。什么的。

上面的代码在 Windows 的 Edge 和 Chrome 中都可以正常工作。 (如果 Windows 键是唯一的修饰符,Windows 将捕获它,但您的应用程序可以很好地捕获像 Ctrl-Meta-x 这样的组合)。例如,当我输入 C-S-M-Q A-Q 时,上面的代码在 Windows 中的 Edge 和 Chrome 中具有相同的输出:

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 + 小键盘方面存在一些问题号)。

我上次使用 Mac 时,它同时支持 Meta 和 Alt 键,所以这个问题可能也适用于 Mac。

在 Linux 中,请确保您的计算机具有可用的 Meta 和 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 和其他程序可以正确捕获所有修饰键。

在 Linux Chrome 中确定与keydown 事件一起按下的修饰符的正确方法是什么?

【问题讨论】:

    标签: javascript linux google-chrome keyboard-input


    【解决方案1】:

    我想出了在 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 还是有问题……如果你同时按住 Shift 键,它会将 key 的值从 Alt 更改为 Meta。所以我们必须使用:

    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

    【讨论】:

      【解决方案2】:

      我认为键盘事件的最佳方法是KeyboardEvent.getModifierState() KeyboardEvent.getModifierState() 方法返回指定修饰键的当前状态:如果修饰键处于活动状态,则返回 true。

      • 至少从 Firefox 48 开始,⊞ Windows 键不被视为“元”键。按下 ⊞ Windows 时,KeyboardEvent.metaKey 为 false。

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

      另外,我总是检查用户代理,然后我会向用户发送通知,告知用户哪个密钥可用。

      【讨论】:

      • Windows 键不是“元”键?您是否使用在“Ctrl”和“Alt”之间有其他键的键盘?或者然后你的“元”键在哪里(在其他程序中,正在工作)?
      • 感谢您的链接。我尝试使用keyArgAltMeta 的值getModifierState()。结果与altKeymetaKey 字段大致相同......它适用于Firefox,但不适用于Chrome。 Chrome 认为我的 Meta 键是 Alt...并且它认为我的 Alt 键本身具有 Alt 修饰符,但在与另一个键组合时没有注意到。
      猜你喜欢
      • 2011-03-21
      • 2011-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多