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
withAnyEvent::I3
- to communicate with i3 IPC -
bash
withgrep
,sed
andxargs
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
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;
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
Bye!
Top comments (0)