linuxmacosemacskeyboardkarabiner

Karabiner for Linux?


Background: for the past five years or so, I have been using Mac hardware (high end MacBook Pro laptops for the most part) and software after many years of using Gnu/Linux on typical PC hardware with ergonomic keyboards. More importantly, as a heavy Emacs user, the switch to Mac was painful, with the Apple standard short keyboard both maddening and unavoidable. I prevented RSI onset by using the Karabiner tool to make two small but very important changes: 1) changing the capslock key to generate a menu (f13) key when pressed alone and a control key modified keycode when pressed with another key; 2) changing the return key in a similar fashion, get return when pressed alone and a control key modified keycode when pressed with another key. Disappointed with recent Apple decisions for both hardware and software, I am now moving back to Gnu/Linux (Ubuntu if it matters) but sticking with Mac laptops.

Question: since Karabiner is an OS X only tool with no readily available Gnu/Linux counterpart, it looks like I will have to write and/or modify some code to achieve the capslock and return key dual function behaviors Karabiner enables. The Karabiner author writes that xbindkeys and rbindkeys do key remapping but at first glance they do not seem to handle the dual function behaviors. Now I am wrestling with porting Karabiner or creating a new tool entirely. And no doubt there may be other approaches as well. So my question is: what programming advice would you suggest for solving this problem? Especially one that can be developed in hours, days or weeks rather than in months.

Notes:

1) There are different approaches involving changes of behavior such as swapping control and command keys. Many have been tried with varying degrees of satisfaction. Karabiner's dual function approach is, IMHO, far and away, the most effective in that it provides control key symmetry on the keyboard home row, and for all applications!

2) Different hardware is also likely to be suggested. I've tried Dell, HP, Lenovo, Acer systems and looked at a lot more. None are comparable to the combined power, size, feel, and style of the Apple top end products, albeit at a premium price. For example, the Dell Precision 7510 is bulky and has a trackpad that feels like sandpaper; the Lenovo X1 (a very nice system) lacks a Thunderbolt port; etc.

3) External keyboards are also a non-starter because of the laptop requirement; an external keyboard on the plane or train is not happening.


Solution

  • You can achieve this on Waylan, a TTY or X11 using Interception Tools, which talks directly with libevdev and libudev.

    Wayland, TTY or X11

    Install Interception Tools and a plugin such as caps2esc or interception-k2k. Then you need to configure Interception to use this plugin. For caps2esc, you can use the following /etc/udevmon.yaml file:

    - JOB: "intercept -g $DEVNODE | caps2esc | uinput -d $DEVNODE"
      DEVICE:
        EVENTS:
          EV_KEY: [KEY_CAPSLOCK, KEY_ESC]
    

    Then run it as root:

    nice -n -20 /usr/bin/udevmon -c /etc/udevmon.yaml

    You should make sure it starts on login. For systemd, you can use the following service:

    [Unit]
    Description=udevmon
    
    [Service]
    ExecStart=/usr/bin/nice -n -20 /usr/bin/udevmon -c /etc/udevmon.yaml
    
    [Install]
    WantedBy=multi-user.target
    

    X11-only

    As an alternative or on older systems without udev, you can use setxkbmap and xcape.

    First change Caps Lock to act as a Ctrl modifier:

    setxkbmap -option caps:ctrl_modifier

    Then set Caps Lock to act as Menu key when pressed for less than the timeout (the default is 500 ms):

    xcape -e 'Caps_Lock=Menu'

    xcape runs as a daemon, so you need to ensure it starts on login. setxkbmap sets the keyboard layout for the current X session only, you can set it permanently on xinitrc, xprofile or X configuration files.


    P.S. For those that want to use an external keyboard, the open source (software and hardware) Ultimate Hacking Keyboard (UHK) allows this functionality.