Spanish focused compose key

Content

Why?

I don't like the Spanish layout. In my head, it makes more sense to have ; /: and ' /" sharing keys than ; /, and ' /? , among others. I also don't like needing a key dedicated to a barely used character like Ñ or ¨ . Furthermore, it sometimes isn't installed on PCs

US-international isn't great either. In Windows, it was quite annoying because ' and " don't register the corresponding keys, but instead wait for the next keypress, to know whether it should be an accent or not, having that key serve both functions. This is really annoying, especially for a vim user that uses marks for navigation. But its main issue is that it works slightly differently in every OS, destroying muscle memory.

The X11 compose key1 in Linux is the closest thing to perfect for me. It does require an extra keypress compared to some of the other solutions, but it's for not so frequently used keys. It allows you to write some previously impossible characters (like fractions, subindices and more). But best of all, it doesn't make any modifications to the standard layout, while still being compatible with almost any Linux app (unlike writing Unicode characters with ctrl-shift-u , more on that later). That said, it's still a Linux specific solution.

I wanted a similar solution, that works the same in any OS, while ideally getting rid of that extra keypress that the compose key requires. To achieve this, I narrowed down the characters to the ones that were actually necessary to a Spanish speaker (accents, ñ, ü).

Why not use QMK's builtin Unicode support?

Two reasons. The first one is that I don't really need the entire Unicode, I just want a couple specific characters. Secondly, since it attempts to support the entire Unicode, it ends up with limitations I'm not happy with, mainly:

  • In Linux, it uses ctrl-shift-u to print Unicode characters. This doesn't work in most apps2, including my terminal emulator, where I do most of my writing. It can also be quite annoying when it doesn't work, since it will activate a random shortcut in whatever app you're using.
  • In Windows, it requires a separate program (or editing the register, but it's not a recommended method3)

Overview

Despite me calling it "compose key", it doesn't actually allow to combine two characters just as the key by the same name in Linux allows you to do so. Instead, each character has assigned an alternate "composed" character to output instead of itself. For instance, vowels print their accented version (a á ), n gets changed to ñ , and g outputs . Also I added d which is turned into ° .

It can be used in two ways. Firstly, you can tap the compose key. The first key you tap after that will be composed (and if it's not possible, it'll output the unmodified keypress). The second option is to hold the compose key. Any key pressed while the compose key is down will be composed if possible (and work as normal if not).

There are also a few more functionalities. A double tap of the compose key will press Right Alt. This is so that in Linux, I can still use the regular compose key if I want to print some unusual character. Finally, a triple tap will switch between Linux mode and Windows mode. This is how I solved multi platform compatibility. All compose actions will work the exact same on both OSs.

Add it to your layout

First, copy my compose.c file (and its corresponding header file) to a features/ directory. Include it in your keymap.c:

#include "features/compose.h"

Don't forget to add the source file as a SRC in your rules.mk file too:

SRC += features/compose.c

Then, in your process_record_user (that's probably in your keymap.c file) you add a call to process_record_compose , like so:

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    if (!process_record_compose(keycode, record)) { return false; }
    ...
}

After that, you must add the COMPOSE key to your layout (it is defined in compose.h).

For this to work in Linux, you must have enabled the compose key4 For Windows, no extra configuration is required.

Finally, unless you're using the Moonlander keyboard, you'll want to remove the ML_LED_* calls, or replace them for the appropriate LED control macros for your keyboard.

How it works

The COMPOSE key uses a trick described here to easily detect whether a key is being tapped or held, to know if it should behave as a one shot modifier or not. In any case, that information is saved into a composing variable.

Then, if composing is true and a composible key is pressed, it is intercepted and a string of keys is sent instead. In Linux, I leverage the real compose key1 to print the special characters. In Windows, I used the ASCII input method (Alt + Numpad numbers). A platform variable is kept, which is swapped when a triple tap is detected.

If a non-composible key is pressed while composing is true , the process_record_compose function just returns true , indicating that it should be processed as normal.

Possible improvements

There are a three things I didn't implement, mainly because I don't need them. The first one is key repeat. In Spanish, none of these characters are ever used more than once in a row, so there'd be no use for that.

The second one is capitalization of these characters in Windows. Since in that OS it works by using ascii keycodes, it'd have to be implemented for each letter separately, and I didn't deem it worth the hassle (or the extra bytes). In Linux, capitalization both through Shift and through Caps Lock works fine, since it's implemented using the compose key.

Finally, I didn't implement support for MacOS (or any other OSs for that matter) either. It should be possible to do so for any OS that supports some kind o Unicode/ASCII character input.


  • 2 This may not be an issue for you, it does work in web browsers (I tested Firefox and Chromium), and some text editors (Geany at least. I think for Vim, it'll depend on your terminal emulator, but for Alacritty it didn't work).
  • 4 I use right alt, you can change which key will be used in compose.c