Would be really nice to have the module showing current keyboard layout. Or maybe a help to write the custom module script with this capability.
Create a custom module with something like this in a script and run it in the exec: ?
setxkbmap -query | grep layout | cut -f2 -d":" | tr -d '[:space:]'
@harishkrupo it doesn't work. It always shows us (my default layout) even when I use another layout.
okay, will need to check. How do you pick a different layout?
@harishkrupo If you're using Sway: https://github.com/swaywm/sway/wiki#input-configuration
I have opened a PR for this issue: https://github.com/Alexays/Waybar/pull/85
if somebody needs it:
"custom/lang": {
"exec": "swaymsg -t get_inputs|grep -4 'AT T'|tail -1|sed 's/.*: //;s/\"//g'|cut -c 1-2|tr '[a-z]' '[A-Z]'",
"interval": 1
},
grep -4 'AT T' finds my particular keyboard, you probably want to change values in the scriptthis polls it every second, but ideally it should work as in pulseaudio module, to update whenever layout updates.
for that it needs some integration with wlroots/sway or something, and values like "name": "AT T" to identify which exact keyboard to use
@rvi64 Thanks!
Similar suggestions here:
There is an ongoing work to create a new protocol to get this information. See here
Unfortunately, I got busy with some other work . :(
I will try to start work on this again.
here's a version without jq, only unix utils, shows EN by default, and first two upper case letters otherwise
"custom/lang": {
"exec": "swaymsg -t get_inputs | grep layout_name | grep -v En | awk 'END{if(NR == 0){print \"EN\"}else{print toupper(substr($2,2,2))}}'",
"interval": 1,
"format": "{} ο"
},
here's a another version with only unix utils, shows proper language two letters shortcut
.config/waybar/modules/layout.sh
#!/bin/bash
KEYBOARD=$(swaymsg -pt get_config | awk '{if ($1 == "input") {name=$2}; if($1 == "xkb_layout") {print name; exit}}')
ACTIVE_LANGUAGE=$(swaymsg -t get_inputs | grep -5 $KEYBOARD | tail -1 | sed 's/.*"\(.*\)".*$/\1/gi')
MANPAGE=$(man --where xkeyboard-config)
case `file -bi $MANPAGE | grep -o "^[^/]*/[^;]*"` in
'application/x-gzip') CAT='zcat';;
'application/x-bzip2') CAT='bzcat';;
'application/x-tar') CAT='tar -O -xf';;
'application/x-xz') CAT='xzcat';;
'text/plain') CAT='cat';;
esac
$CAT $MANPAGE | awk -F'[\t(]' -v var="$ACTIVE_LANGUAGE" 'index($0,var)>=1 {print $1; exit}'
.config/waybar/config
"custom/layout": {
"exec": "~/.config/waybar/modules/layout.sh",
"interval": 1,
"format": "{} ο"
}
EDIT: add support for other man formats. Sadly /usr/share/X11/xkb/rules/evdev.xml is not contain needed informations
gzip: skipping: /usr/share/man/man7/xkeyboard-config.7.bz2 unrecognized format
You assume that man page is compressed with gzip.
Also, don't you think, parsing man isn't the right way to do this? The right way is parsing /usr/share/X11/xkb/rules/evdev.xml I guess.
@eternal-sorrow
EDIT2: I change to script to not start every time
.config/waybar/modules/layout.sh
#!/bin/bash
KEYBOARD=$(swaymsg -pt get_config | awk '{if ($1 == "input") {name=$2}; if($1 == "xkb_layout") {print name; exit}}')
MANPAGE=$(man --where xkeyboard-config)
case `file -bi $MANPAGE | grep -o "^[^/]*/[^;]*"` in
'application/x-gzip') CAT='zcat';;
'application/x-bzip2') CAT='bzcat';;
'application/x-tar') CAT='tar -O -xf';;
'application/x-xz') CAT='xzcat';;
'text/plain') CAT='cat';;
esac
while true; do
ACTIVE_LANGUAGE=$(swaymsg -t get_inputs | grep -5 $KEYBOARD | tail -1 | sed 's/.*"\(.*\)".*$/\1/gi')
$CAT $MANPAGE | awk -F'[\t(]' -v var="$ACTIVE_LANGUAGE" 'index($0,var)>=1 {print $1; exit}'
sleep 1
done
.config/waybar/config
"custom/layout": {
"exec": "~/.config/waybar/modules/layout.sh", // DO NOT RUN multiple times
"format": "{} ο"
}
Here's my python version. You'll need the latest git version of acrisci/i3ipc-python installed.
Set KBD_NAME to the name of your keyboard device (see swaymsg -t get_inputs).
#!/usr/bin/env -S python3 -u
import time
import i3ipc
KBD_NAME = "1:1:AT_Translated_Set_2_keyboard"
sway = i3ipc.Connection()
while True:
inputs = sway.get_inputs()
keyboard = [i for i in inputs if i['identifier'] == KBD_NAME][0]
layout = keyboard['xkb_active_layout_name']
print(layout[:2].lower())
time.sleep(1)
We can get updates from swaymsg -mrt subscribe (no "interval" setting needed) https://github.com/Alexays/Waybar/pull/85#issuecomment-560100037
Here's my python version. You'll need the latest git version of acrisci/i3ipc-python installed.
SetKBD_NAMEto the name of your keyboard device (seeswaymsg -t get_inputs).#!/usr/bin/env -S python3 -u import time import i3ipc KBD_NAME = "1:1:AT_Translated_Set_2_keyboard" sway = i3ipc.Connection() while True: inputs = sway.get_inputs() keyboard = [i for i in inputs if i['identifier'] == KBD_NAME][0] layout = keyboard['xkb_active_layout_name'] print(layout[:2].lower()) time.sleep(1)
Not work for me.
print inputs [<i3ipc.replies.InputReply object at 0x7f988d156dc0>, <i3ipc.replies.InputReply object at 0x7f988d1379d0>, <i3ipc.replies.InputReply object at 0x7f988d137b50>, <i3ipc.replies.InputReply object at 0x7f988cfc0910>, <i3ipc.replies.InputReply object at 0x7f988cd69d60>, <i3ipc.replies.InputReply object at 0x7f988cd69dc0>, <i3ipc.replies.InputReply object at 0x7f988cd69e20>, <i3ipc.replies.InputReply object at 0x7f988cd69e50>, <i3ipc.replies.InputReply object at 0x7f988cd69e80>, <i3ipc.replies.InputReply object at 0x7f988cd69eb0>]
Traceback (most recent call last):
File "./layout.py", line 13, in <module>
keyboard = [i for i in inputs if i['identifier'] == KBD_NAME][0]
File "./layout.py", line 13, in <listcomp>
keyboard = [i for i in inputs if i['identifier'] == KBD_NAME][0]
TypeError: 'InputReply' object is not subscriptable
@exdeniz This version is very outdated. It uses polling and old i3ipc API. Use that one https://github.com/Alexays/Waybar/pull/85#issuecomment-526235072 or one of others from that thread.
Sway IPC protocol now has subscribe message type. Here is my Waybar config entry that prints current layout:
"custom/layout": {
"tooltip": false,
"exec": "swaymsg -mrt subscribe '[\"input\"]' | jq -r --unbuffered \"select(.change == \\\"xkb_layout\\\") | .input | select(.identifier == \\\"1:1:AT_Translated_Set_2_keyboard\\\" and .type == \\\"keyboard\\\") | .xkb_active_layout_name | .[0:2] | ascii_upcase\""
},
However:
sh process and it keeps running until you kill swaymsg -mrt subscribe ["input"] process."1:1:AT_Translated_Set_2_keyboard" - it seems that keyboard identification is a fundamental problem to wayland protocol. There seems to be no reliable way to differentiate between a real keyboard and "keyboards" that are actually power buttons and other special buttons.jqI would be really happy to see this __inside__ Waybar.
@Hexawolf I created pull request with waybar module which shows keyboard layout. Yes it still use 1:1:AT_Translated_Set_2_keyboard but only on startup. Also it can show short layout names from /usr/share/X11/xkb/rules/evdev.xml.
One might want to use a more generic version while pull request is still not merged:
"custom/layout": {
"tooltip": false,
"exec": "swaymsg -mrt subscribe '[\"input\"]' | jq -r --unbuffered \"select(.change == \\\"xkb_lay
out\\\") | .input | select(.type == \\\"keyboard\\\") | .xkb_active_layout_name | .[0:2] | ascii_upcase\""
}
I just built a little bit on the previous answers and uses the following to show flags for layouts in waybar.
"custom/keyboard_layout": {
"exec": "waybar_sway_keyboard_layout",
"tooltip": false
}
waybar_sway_keyboard_layout
#!/bin/sh
DEFAULT_LAYOUT="English (US)"
# Kill old instances since waybar don't kill them when exited
[ "$(pgrep -a 'swaymsg' | grep -c '["input"]')" -gt 0 ] &&
pgrep -a 'swaymsg' | grep '["input"]' | cut -d ' ' -f1 | xargs -r kill
# Sleep for a short while in order to prevent startup issues in waybar
sleep 0.5
keyboard_flag() {
while read -r layout; do
if [ "$layout" = "English (US)" ]; then
layout_waybar="πΊπΈ"
elif [ "$layout" = "Swedish" ]; then
layout_waybar="πΈπͺ"
else
layout_waybar="$layout"
fi
printf '%s\n' "$layout_waybar"
done
}
echo "$DEFAULT_LAYOUT" | keyboard_flag
swaymsg -mrt subscribe '["input"]' | jq -r --unbuffered "select(.change == \"xkb_layout\") | .input | select(.type == \"keyboard\") | .xkb_active_layout_name" | keyboard_flag
I made a simple C program for displaying layouts using sway IPC subscription:
https://github.com/Hexawolf/swaylay
I've a custom python script to get the layout using i3ipc library (python-i3ipc). it subscribes to input changes to get notified when the layout changes without the need to poll in a loop.
xkblayout.py:
#!/usr/bin/env -S python3 -u
# vi:syntax=python
import os
import signal
import i3ipc
pri_layout_code = "EN"
sec_layout_code = "AR"
sec_layout_name = "arabic"
input_event_change = "xkb_layout"
sway_sock_path = os.environ["SWAYSOCK"]
sway = i3ipc.Connection(socket_path=sway_sock_path, auto_reconnect=False)
def on_posix_signal(sig, frame):
sway.main_quit()
signal.signal(signal.SIGHUP, on_posix_signal)
signal.signal(signal.SIGINT, on_posix_signal)
signal.signal(signal.SIGQUIT, on_posix_signal)
signal.signal(signal.SIGTERM, on_posix_signal)
# print the primary layout as it's the default
print(pri_layout_code)
def on_input_change(conn, event):
if event.change != input_event_change:
return
if event.input.xkb_active_layout_name.lower() == sec_layout_name:
print(sec_layout_code)
else:
print(pri_layout_code)
def on_shutdown_or_reload(conn, event):
conn.main_quit()
sway.on(i3ipc.Event.INPUT, on_input_change)
sway.on(i3ipc.Event.SHUTDOWN, on_shutdown_or_reload)
sway.on(i3ipc.Event.SHUTDOWN_EXIT, on_shutdown_or_reload)
sway.on(i3ipc.Event.SHUTDOWN_RESTART, on_shutdown_or_reload)
sway.on(i3ipc.Event.BARCONFIG_UPDATE, on_shutdown_or_reload)
sway.main()
make sure you make xkblayout.py executable
config:
.......
.......
"custom/xkblayout": {
"exec": "path/to/xkblayout.py",
"format": "ο {}",
"tooltip": false
},
.......
.......
if I read correctly, #659 also interact just to input change
@krtko1 yes it does subscribe to input change events
I rewrote a jq version in sed and embedded it into the single 'exec' object, so it doesn't need any external script execuion:
"exec": "swaymsg --type get_inputs | grep \"xkb_active_layout_name\" | sed -u '1!d; s/^.*xkb_active_layout_name\": \"//; s/ (US)//; s/\",//' && swaymsg --type subscribe --monitor '[\"input\"]' | sed -u 's/^.*xkb_active_layout_name\": \"//; s/\",.*$//; s/ (US)//'",
FWIW those running Waybar in Sway can just use sway/language: https://github.com/Alexays/Waybar/blob/master/man/waybar-sway-language.5.scd
FWIW those running Waybar in Sway can just use
sway/language: https://github.com/Alexays/Waybar/blob/master/man/waybar-sway-language.5.scd
Great, I just added it and it seems to work. Do you think it would be possible to add also the variant together with the layout name?
Most helpful comment
here's a version without jq, only unix utils, shows EN by default, and first two upper case letters otherwise