Installation
The keyboard I built this around was a Corsair K70 Lux. Unfortunately if you’re looking to try to use this for yourself, you’re going to be limited to a Corsair keyboard, since everything is built on ckb-next. If you do want to try this yourself with a Corsair keyboard, it’s important to note that the K70 Lux only has red LEDs, extending this to work with different colors shouldn’t be that far of a stretch, but for now, it’s designed to work as a simple on/off.
Dependencies
The only dependencies that ckb-animation
are:
ckb-next
: for providing the Corsair controller driversystemd
: for making dealing with the fact that Corsair’s driver behavior depends on a GUI interface easier.xinput
: for identifying key press and release events for control, shift, super, and alt keys.
Installing
The full installation instructions are available on the ckb-animation repo. Ideally they should be as simple as,
$ git clone https://github.com/blockjoe/ckb-animation.git
$ cd ckb-animation
$ ./install.sh
I’ve only built this around my ease of use with my K70 Lux on an Ubuntu based
system though, and any other use cases remain currently untested. Assuming a
clean install, the ckb-animation
service will be enabled for the user, and
will automatically start/stop with hot plugging of a ckb-next
supported
keyboard.
Using and Configuring the Keyboard Shortcuts.
With the service running, the daemon is accessible from the ckb-animation
program. This daemon provides commands for the basic start/stop/restart/status
commands, but also commands for managing which keys are to be illuminated when
a chord is held. A chord represents holding down any of the modifier keys, Alt,
Control, Super (Meta/Windows), Shift, or certain combinations of them.
Currently the chords that are represented in the animation are:
- Control
- Alt
- Super
- Control+Alt
- Control+Shift
- Control+Super
- Alt+Shift
- Alt+Super
- Super+Shift
- Control+Alt+Shift
Holding any of these keys will light up a set of keys that represent available keyboard shortcuts that are available for that chord. For example holding in Control+Alt might illuminate Esc, Delete, l, while holding just Alt might illuminate Tab and the arrow keys.
ckb-animation
ships with shortcuts that represent my current setup, but these
certainly aren’t a one size fits all solution. The preconfigured keys can be
viewed with the view
command. For example, if we wanted to see the keys that
represent Alt shortcuts, we would run:
$ ckb-animation view chord alt
Keys for alt
grave
tab
f3
f4
home
up
left
right
h
j
k
l
Let’s say that in our setup, we don’t use Alt+H, Alt+J, Alt+K, or Alt+L for anything, we can modify the configuration on the fly, and it will automatically update if we were to run:
$ ckb-animation remove alt h j k l
Immediately after running, it will be clear that when holding Alt, the h/j/k/l keys are no longer illuminated. Let’s say that we have shortcuts bound for Alt+F5-Alt+F9, adding these in would be as simple as:
$ ckb-animation add alt f5 f6 f7 f8 f9
The behavior extends to any of the supported multi-key chords as well – the
only requirement is that the combination of the keys be separated by a -
. The
order and first letter case doesn’t matter, and some keys have multiple names
that are all valid. For example ctrl-super
, Control-Windows
, and
meta-control
all identify the same chord.
The keys are expected to be named in the format that ckb-next
uses to
identify them. The expected names of the keys can be discovered by running:
$ ckb-animation view keys
Name Key
---------------
mr MR
m1 M1
m2 M2
m3 M3
light Brightness
lock Windows Lock
mute Mute
volup Volume Up
voldn Volume down
...
This isn’t always the most convenient way to find the key that you wanted mid-command. Installing the bash autocomplete makes this process a lot easier. Tabbing for the key on the add command gives a full list of available keys to be added.
$ ckb-animation add ctrl <tab><y>
Display all 142 possibilities? (y or n)
0 f1 g8 n r
1 f10 g9 next ralt
2 f11 grave num0 rbrace
3 f12 h num1 rctrl
4 f2 hash num2 right
5 f3 henkan num3 rmenu
6 f4 home num4 ro
7 f5 i num5 rshift
8 f6 ins num6 rwin
9 f7 j num7 s
a f8 k num8 scroll
b f9 katahira num9 slash
bslash g l numdot space
bslash_iso g1 lalt numenter stop
bspace g10 lbrace numlock t
c g11 lctrl numminus tab
caps g12 left numplus u
colon g13 light numslash up
comma g14 lock numstar v
d g15 lshift o voldn
del g16 lwin p volup
dot g17 m pause w
down g18 m1 pgdn x
e g2 m2 pgup y
end g3 m3 play yen
enter g4 minus prev z
equal g5 mr prtscn
esc g6 muhenkan q
f g7 mute quote
$ ckb-animation add ctrl
Tabbing for the key on the remove command will only list keys that are currently defined for that command as well.
$ ckb-animation remove alt <tab>
f3 f4 grave h home j
k l left right tab up
$ ckb-animation remove alt
I find that I pretty frequently need to make a minor change where I create a
new chorded shortcut, or change an existing one, and this workflow makes
updating the keyboard animation pretty seamless. On top of that, the chords are
saved via files in the ~/.config
directory, which makes it possible to manage
the animation configuration as you would any other dotfiles.
Potential Improvements
For now this solution works pretty flawlessly for my given setup, but assuming I were to change things, there’s a few things that I would probably want to build upon.
More Colors
I currently have 4 main categories of chord shortcuts:
- KDE
- Terminator
- Vim
- Firefox
The KDE shortcuts should be accessible at all times, but the shortcuts associated
with the other groups will only be relevant if the application is open and in focus.
If I had more than one color to work with, I could represent at least which context
that shortcut applies to. In my case, Alt+hjkl
corresponds to movement in KDE windows,
Super+hjkl
corresponds to movement in Terminator splits, and Ctrl+hjkl
corresponds
to movement in Vim splits. Seeing that represented only in one color means that I know I
have shortcuts for 3 different kinds of movement on hjkl chords, but having more colors
means that I could immediately tell the difference between each. Additionally, having
the ability to encode application specific information might motivate shortcuts only being
displayed if the relevant context has focus.
Dynamic Chords
Currently the chords are hard-coded around the modifiers that are relevant to me. The ckb-animation repo has details about how to manually add support for a new chord. If I were to move to a workflow that utilizes many modifier keys present in terms of macro keys, making defining new chords accessible from the CLI might be worth considering.
Remove the systemd dependence
The only reason I made this into a systemd service instead of just calling
ckb-animation start/stop
directly from udev has to do with the fact that
ckb-next
currently binds itself to a GUI session. Since ckb-next
is run as
the user, I felt it was consistent to have ckb-animation
run as the user as
well. udev does provide options for running a script as a user, but it didn’t
look nearly as straightforward as making a user systemd
service.
Remove the X dependence
The solution isn’t currently compatible with Wayland, as I currently
rely on xinput
for identifying the keyboard to monitor, and then monitoring
the events of that keyboard for determining the key down/release events for
identifying the current chords. There’s nothing here that binds me to xinput
besides the fact that is was what was familiar.
The following two lines are the only two in which I directly rely on
xinput
# find the keyboard id
keyboard_id=$(xinput list | grep "vKB" | cut -f 2 | cut -d"=" -f 2)
# read the keyboard event loop
xinput test "$keyboard_id" | while read event; do
I should be able to change this to where I can use libinput list-devices
to
look for the keyboard, and then use libinput debug-events --show-keycodes
/dev/input/eventX
to get my loop of keyboard events. Instead of extracting the
id from xinput list
, I would want to extract the kernel device with libinput
list-devices
. Passing along the show-keycodes
would mean that I can reuse
the base logic for identifying key up/down events for my chord keys, although
the pattern I would be looking for in the line would change slightly. A left
control press/release event currently looks like
key press 37
key release 37
would instead look like
event2 KEYBOARD_KEY +1.784s KEY_LEFTCTRL (37) pressed
event2 KEYBOARD_KEY +1.880s KEY_LEFTCTRL (37) released
This is change that could be implemented in where I currently define the key
up/down patterns at the top of bin/ckb-animation
, but one that I probably
won’t get around to until I migrate over to Wayland myself. I’d imagine this
would look something similar to the following:
down=" pressed" # down="key press "
up=" released" # up="key release "
ctrl_l_up="(37)${up}" # ctrl_l_up="${up}37"
ctrl_l_down="(37)${down}" # ctrl_l_down="${down}37"