I have setup my QMK-enabled keyboard to output Unicode characters. In short, that was adding UNICODE_ENABLE = yes line to the rules.mk file and adding the following two lines to the config.h file.


And afterward adding (for example) UC(0x2227) and UC(0x2228) to keymap.c file in order to be able to type and characters. Now, this works fine in most GUI applications like web browsers, etc, it also works in Terminal (GUI). However in Emacs instead of and I get 2227 or 2228 SPC characters inserted in a buffer :(

I have tried setting (set-keyboard-coding-system 'utf-8) without any effect.

Switching to other Unicode insertion modes from my default UC_LNX, which gives the above behavior, results in:

  • for UC_OSX: same as pressing-and-holding Ctrl key and hitting digits (2227);
  • for UC_WIN: same as above with extra screen "blink";
  • for UC_WINC: only raw string u2227 gets directly inserted in the buffer.

The behavior for UC_LNX seems to be explained by Emacs interpreting the Unicode insertion as the following key-sequence: C-2 C-2 C-2 C-7 SPC, thus inserting 2227 space characters... :/

I am using GUI version of GNU Emacs running on CentOS 7 with GNOME Shell 3.28.3.

Has anybody any idea on how to get Emacs to correctly interpret the Unicode characters inserted directly from keyboard OR how to augment QMK software with Unicode insertion method that Emacs will understand UC_EMACS?

4 Answers 4


Problem solved (or at least "workarounded"). One way to input a Unicode character on GNU Linux systems is for user to press Ctrl+Shift+U followed by the character-specific code and finally by space to terminate the character entry. This key sequence was sent from keyboard. However, for GNU Emacs this key sequence, C-u (translated from C-S-u), runs the command universal-argument which waits for user input (a number) followed by some command. Because I have tested my Unicode input on LOGICAL_AND and LOGICAL_OR which have key-codes 2227 and 2228 these numbers were interpreted as arguments provided for the following "command" and the next keystroke was space, thus 2227 or 2228 spaces were introduced at the point in the buffer.

The best and quickest solution that I have come with was to introduce a new mode of Unicode character entry to the QMK. To the existing modes, namely

    UC_OSX,    // Mac OS X using Unicode Hex Input
    UC_LNX,    // Linux using IBus
    UC_WIN,    // Windows using EnableHexNumpad
    UC_BSD,    // BSD (not implemented)
    UC_WINC,   // Windows using WinCompose (https://github.com/samhocevar/wincompose)

I have added a new one UC_EMACS based on the way that Emacs accepts unicode character entries. Thus, confirming yet again that, GNU Emacs is an operating system ;)

QMK contains three functions that were crucial in this matter: unicode_input_start, unicode_input_finish and unicode_input_cancel. Thus adding

        case UC_EMACS:

to the unicode_input_start function allows us to start insertion of unicode character in Emacs fashion, that is, C-x 8 RET (translated from C-x 8 <return>) that runs command insert-char. Then the code is inserted by QMK. Finally in unicode_input_finish I have added

        case UC_EMACS:

Some other minor modifications were required in files:

  • qmk_firmware__qmk/quantum/process_keycode/process_unicode_common.c
  • qmk_firmware__qmk/quantum/process_keycode/process_unicode_common.h
  • qmk_firmware__qmk/quantum/quantum_keycodes.h
  • What runs after universal-argument to insert the character?
    – ideasman42
    Sep 18, 2022 at 9:41

Here is an alternative solution that doesn't need special workarounds. This provides a function to trick emacs so that it accepts the unicode sequence:

;; enable standard linux unicode input
(define-key global-map (kbd "C-S-u") 'read-unicode-char)

(defun read-unicode-char (c1 c2 c3 c4 _trailing_space_ignored)
  "Convert unicode input C1 C2 C3 C4 to the corresponding insert char call."
  (interactive "c\nc\nc\nc\nc")
  (insert-char (string-to-number (format "%c%c%c%c" c1 c2 c3 c4) 16)))
  • This works pretty well if you're okay with overriding whatever C-S-u is bound to by default!
    – rien333
    Feb 4 at 18:42

Based on hyour description, this keyboard sends events which neither the Linux kernel nor the X11-layer understand as "single-key press" and it's instead some higher layer in some toolkit(s) and/or applications which decodes it. I'd consider this as a shortcoming that should probably be best solved by some kernel-level driver.

But as for a workaround in Emacs, you could try something like (100% guaranteed untested):

(advice-add 'self-insert-command :around
  (lambda (orig-fun &rest args)
    (if (or (not (eq last-command-event ?\s))
            (< current-prefix-arg 128))
        (apply orig-fun args)
      (setq last-command-event current-prefix-arg)
      (setq current-prefix-arg nil)
      (call-interactively 'self-insert-command))))

I agree with @tristanC that I would fix the compatibility within Emacs rather than within QMK such that the QMK bindings still work with other programs.

This is a generic solution that supports what QMK is doing also allows the usual manual entry as I was used to using before QMK (something like C-S-u f c SPC to insert ü):

(defun my/insert-unicode-char ()
  (let* ((digits (named-let gather-hex-digits ((digits nil))
                   (let ((digit (read-char)))
                     (if (not (or (<= ?0 digit ?9)
                                  (<= ?a digit ?f)
                                  (<= ?A digit ?F)))
                       (gather-hex-digits (cons digit digits))))))
         (code (string-to-number
                (apply 'string (reverse digits))
    (insert-char code)))

(evil-global-set-key 'insert (kbd "C-S-u") 'my/insert-unicode-char)

Here it is bound for evil, but you can define it just as well

Note that this code requires lexical binding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.