Skip to content

macOS: Option+key producing a backtick on AltGr-style custom layouts is silently swallowed by completionKeymap's mac-only Alt-backtick binding #429

Description

@vlcinsky

I found I cannot enter the backtick character in the ZenNotes editor window.

The cause: the stock CodeMirror completionKeymap (which ZenNotes includes
unfiltered) binds Alt-` to startCompletion on Mac, so the keystroke is
consumed before the character is inserted.

Note: if you wonder why I use an AltGr-style layout on a Mac — years of muscle
memory for touch typing. My touch typing teacher
Jaroslav Zaviačič
(trainer of many world champions) explained to me that using AltGr allows
typing national (e.g. Czech) characters plus special programming characters
without switching keyboard layouts. And I have to admit — yes, it makes a real
difference. Fun fact: he is credited with inventing the tactile marks on the
F and J keys — so you touch his invention many times a day.

Summary

On macOS with a custom AltGr-style keyboard layout (Option layer emits printable characters directly, like Windows/Linux AltGr), pressing the key combination that produces a backtick (`) inserts nothing in the editor. All other Option-produced characters (\, |, @, #, …) insert fine. The character also works fine in plain input fields (e.g. the Settings keymap filter) — only the CodeMirror editor is affected.

Root cause (traced below): @codemirror/autocomplete's stock completionKeymap contains a mac-only binding { mac: "Alt-`", run: startCompletion }. ZenNotes includes ...completionKeymap wholesale in buildEditorKeymap (packages/app-core/src/components/EditorPane.tsx). When the layout emits a literal ` with Option held, the keydown arrives as key: "`", code: "Backquote", altKey: true, CodeMirror's keymap dispatch matches Alt-` , runs startCompletion, and calls preventDefault() — so the character is never inserted.

Users on Apple's stock layouts never hit this because Opt+` there is a dead key (event.key === "Dead"), which never matches the binding. Custom layouts built with Ukelele that mirror Linux/Windows AltGr behavior (a common setup for Czech, Polish, German, and other ISO-layout users) emit the character directly and hit it every time.

Environment

  • ZenNotes 2.14.0 (macOS, Electron desktop build)
  • macOS, MacBook with ISO (Czech) keyboard
  • Custom .keylayout (Ukelele): base layer Czech, Option layer emits AltGr characters directly; the physical key under Esc produces ; unmodified and ` with Option
  • Reproduces identically with Vim mode on and off, in insert mode, after full app restart

Steps to reproduce

  1. Install a custom macOS keyboard layout whose Option layer outputs ` directly on some key (i.e. not as a dead key). I can attach my .keylayout file for a one-minute repro.
  2. Open any note, focus the editor (insert mode if Vim is on).
  3. Press the Option combo that produces `.

Expected: a backtick is inserted (as happens in the Settings filter input, in Obsidian, and in every native macOS text field).

Actual: nothing is inserted; the keystroke is consumed.

Diagnosis

Captured key events (DevTools, capture + bubble listeners):

Opt + backtick key Opt + Q (control, works)
keydown key: "`", code: "Backquote", keyCode: 192, altKey: true key: "\\", code: "KeyQ", keyCode: 220, altKey: true
defaultPrevented at capture false false
defaultPrevented after handlers true false
beforeinput / input never fire fire, \ inserted

Hooking preventDefault on the event prints this call stack:

preventDefault caller
  runHandlers   @ vendor-editor-….js
  handleEvent   @ vendor-editor-….js

runHandlers is CodeMirror's keymap dispatcher. The matching binding is in @codemirror/autocomplete:

const completionKeymap = [
    { key: "Ctrl-Space", run: startCompletion },
    { mac: "Alt-`", run: startCompletion },   // ← consumes the keystroke
    { mac: "Alt-i", run: startCompletion },
    ...

Confirming test: stopping propagation before CodeMirror sees the keydown makes the backtick type correctly (both Vim modes):

window.addEventListener('keydown', e => {
  if (e.altKey && e.code === 'Backquote') e.stopPropagation();
}, true);

Suggested fix

The codebase already has the exact pattern for this: cm-vim-default-keymap.ts filters defaultKeymap's mac-only emacs chords (MAC_EMACS_CHORDS) because stock bindings conflicted with user expectations. The same one-line treatment in buildEditorKeymap fixes this:

...completionKeymap.filter(b => b.mac !== 'Alt-`')

Ctrl-Space (and Alt-i) remain as completion triggers, so no functionality is lost. Consider filtering Alt-i too — any AltGr-style layout that assigns Option+I a printable character has the identical problem with that key.

More generally: on macOS, an Alt-modified keydown whose event.key is a printable character different from the base key is text entry on AltGr-style layouts, and matching it against Alt shortcuts breaks typing. Filtering the known offenders is the pragmatic fix; skipping shortcut matching for such events would be the thorough one.

Here is my .keylayout file (I had to add .xml to get through)

AltGr-cs.keylayout.xml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions