4

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.

#define UNICODE_SELECTED_MODES UC_LNX, UC_OSX, UC_WIN, UC_WINC
#define UNICODE_CYCLE_PERSIST false

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?

Drew
  • 75,699
  • 9
  • 109
  • 225

2 Answers2

2

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:
            tap_code16(LCTL(KC_X));
            tap_code16(KC_8);
            tap_code16(KC_ENTER);
            break;

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:
            tap_code16(KC_ENTER);
            break;

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
1

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))))
Stefan
  • 26,154
  • 3
  • 46
  • 84