~glacambre/firenvim

0a7669d614fed878336a358406f9268f328e6e28 — glacambre 2 years ago 6c5ec95
NeovimFrame.ts: take altGr into account

On MacOS+Swedish layouts, the @ sign is obtained by pressing AltGr+2.
MacOS apparently decides to tell the resulting @ key event that it is
pressed along the `alt` key, which made firenvim treat it as `<A-@>`
rather than plain `@`.
This is fixed by checking if AltGr has been pressed without having been
released before any event. If it has been, do not take the altKey
attribute into account. This means that swedish users can't press
`<A-@>` for now but we'll wait until they complain before further
refactoring our code.
2 files changed, 22 insertions(+), 2 deletions(-)

M src/NeovimFrame.ts
M tslint.json
M src/NeovimFrame.ts => src/NeovimFrame.ts +21 -2
@@ 169,11 169,30 @@ window.addEventListener("load", async () => {
                            augroup END`).split("\n").map(command => ["nvim_command", [command]]));
            });

        let pressingAltGr = false;
        keyHandler.addEventListener("keyup", (evt) => {
            if (evt.key === "Alt" && evt.location === 2) {
                pressingAltGr = false;
            }
        })
        keyHandler.addEventListener("keydown", (evt) => {
            keyHandler.style.left = `0px`;
            keyHandler.style.top = `0px`;

            // Note: order of this array is important, we need to check OS before checking metaa
            // Special case AltRight: both AltLeft and AltRight cause keyevents
            // to have their `altKey` attribute set to true, but only AltLeft
            // events should be treated as special keys.
            if (evt.key === "Alt" && evt.location === 2) {
                pressingAltGr = true;
            }
            // This shouldn't be necessary thanks to the keyup event handler
            // but just to make sure, we reset pressingAltGr when no alt key is
            // pressed.
            if (!evt.altKey) {
                pressingAltGr = false;
            }

            // Note: order of this array is important, we need to check OS before checking meta
            const specialKeys = [["Alt", "A"], ["Control", "C"], ["OS", "D"], ["Meta", "D"]];
            // The event has to be trusted and either have a modifier or a non-literal representation
            if (evt.isTrusted


@@ 182,7 201,7 @@ window.addEventListener("load", async () => {
                                        evt.key !== mod && (evt as any).getModifierState(mod)))) {
                const text = specialKeys.concat(["Shift", "S"])
                    .reduce((key: string, [attr, mod]: [string, string]) => {
                        if ((evt as any).getModifierState(attr)) {
                        if ((evt as any).getModifierState(attr) && (attr !== "Alt" || !pressingAltGr)) {
                            return addModifier(mod, key);
                        }
                        return key;

M tslint.json => tslint.json +1 -0
@@ 11,6 11,7 @@
        "limit": 120
      }
    ],
    "no-big-function": false,
    "no-conditional-assignment": false,
    "no-console": false,
    "no-namespace": false,