DEV Community

Kir Axanov
Kir Axanov

Posted on

Configs. Keyboard LED as layout indicator

Hi!

Using i3wm? Have a fancy keyboard with a nice CapsLock LED, but never actually press CapsLock (not as a remapped Ctrl)?

Me too! Let's convert it into a keyboard layout indicator then!

You can use method described below for things other than keyboard layout and for other LEDs. Happy hacking!

Requirements

  • i3 - targeted window manager, we will use its IPC to subscribe to window change event
  • perl with AnyEvent::I3 - to communicate with i3 IPC
  • bash with grep, sed and xargs utils
  • brightnessctl - to control LED
  • xkb-switch - to monitor keyboard layout change event
  • i3-subscribe.pl - perl script for i3 IPC (source)
  • toggle_capslock_led.sh - our bash script for toggling LED
  • i3ipc_capslock_led.sh - our bash script to start listening for window and layout changes

All scripts below are supposed to be put into ~/Scripts directory - change this path if you need to.

General method

We have a bash script, which checks current keyboard layout and turns the LED on when specified layout is active.

We call this script:

  • when the layout changes
  • when we go to other window (as each window has its own keyboard layout state)

This is the script (toggle_capslock_led.sh) with some comments inside:

#!/usr/bin/env bash # Lights up capslock LED when specified layout is on. # Works for LED on all connected keyboards (e.g. laptop's and external one). # You can also set this to your specific input name, which can be found with: brightnessctl --list # LED_NAMES="input7::capslock" LED_NAMES=$(brightnessctl --list | grep '::capslock' | sed 's/Device .\(.*\). of.*/\1/g') # The layout on which we want LED to be on. # Get available layout names with: xkb-switch -l ON_LAYOUT="us" CURRENT_LAYOUT=$(xkb-switch -p) VALUE=0 if [[ "$CURRENT_LAYOUT" == "$ON_LAYOUT" ]]; then VALUE=1 fi echo "$LED_NAMES" | while read name; do brightnessctl --device="$name" set $VALUE > /dev/null done 
Enter fullscreen mode Exit fullscreen mode

Talking to i3 IPC

Below is the i3-subscribe.pl script for talking to i3 with perl.

To run it you will need to install AnyEvent::I3 for perl.

If you are on NixOS - leave script as it is (it uses nix-shell with perl540Packages.AnyEventI3).

If you aren't on NixOS - replace first two lines with this one: #!/usr/bin/env perl.

#!/usr/bin/env nix-shell #!nix-shell -i perl -p perl perl540Packages.AnyEventI3 # Subscribe to i3wm events via i3ipc. # Source: https://faq.i3wm.org/question/5721/how-do-i-subscribe-to-i3-events-using-bash-easily.1.html # # Usage example for bash: # i3subscribe window workspace | while read -r event; do # ... # done BEGIN { $| = 1 } # flush \n use strict; use warnings; use Data::Dumper; use AnyEvent::I3; use v5.10; my $i3 = i3(); $i3->connect->recv or die "Error connecting to i3"; sub subscribe { my $ev = $_[0]; my $dump = $_[1]; if($i3->subscribe({ $ev => sub { my ($msg) = @_; say "$ev:$msg->{'change'}"; if($dump) { print Dumper($msg); } } })->recv->{success}) { say "Successfully subscribed to $ev-event"; } } my $nextArg = shift; if(!$nextArg) { say "Subscribe to i3-events"; say "Usage: $0 workspace|output|mode|window|barconfig_update|binding [dump]"; say "Example: $0 workspace dump window binding dump"; exit 1; } while($nextArg) { my $arg = $nextArg; $nextArg = shift; my $dump = 0; if($nextArg and $nextArg eq "dump") { $dump = 1; $nextArg = shift; } subscribe("$arg", $dump); } AE::cv->recv; 
Enter fullscreen mode Exit fullscreen mode

Toggle LED

This is i3ipc_capslock_led.sh which starts needed listeners - add this script to autostart and that's it:

#!/usr/bin/env bash # Executes `toggle_capslock_led.sh` script on window change. # Source: https://faq.i3wm.org/question/5721/how-do-i-subscribe-to-i3-events-using-bash-easily.1.html # Run LED switcher on layout change xkb-switch -W | xargs -I{} ~/Scripts/toggle_capslock_led.sh & # Run LED switcher on window or workspace change ~/Scripts/i3-subscribe.pl window workspace | while read -r event; do ~/Scripts/toggle_capslock_led.sh done 
Enter fullscreen mode Exit fullscreen mode

Bye!

Top comments (0)