Waybar icon indicating copy to clipboard operation
Waybar copied to clipboard

Keyboard-state module not detecting capslock status correctly

Open ismay opened this issue 2 years ago • 20 comments
trafficstars

I'm using a moonlander. Waybar does not seem to be detecting the capslock state correctly. Starting waybar with my user as a member of the input group and the keyboard-state module enabled yields:

image

But, the capslock state in the bar behaves a bit weirdly:

  1. On bar start it's correct (shows the unlocked icon when capslock is off)
  2. When pressing capslock it responds correctly as well (shows the lock icon when capslock is on)
  3. But after that it no longer responds to capslock changes. So it keeps showing the lock icon, no matter if capslock is on or off (i.e. it no longer responds to the actual capslock state).

The following script (as a custom module, based on the suggestion here: https://github.com/swaywm/sway/issues/4512#issuecomment-526898845) does work correctly:

#!/bin/bash

capslock=$(cat /sys/class/leds/input17::capslock/brightness)

if [[ "${capslock}" == "1" ]]; then
  echo ''
  echo ''
  echo "locked"
  exit 0
fi

echo ''
echo ''
echo "unlocked"

This is the (truncated) output of swaymsg -t get_inputs:

[...]

Input device: ZSA Technology Labs Moonlander Mark I Keyboard
  Type: Keyboard
  Identifier: 12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I_Keyboard
  Product ID: 6505
  Vendor ID: 12951
  Active Keyboard Layout: English (US)
  Libinput Send Events: enabled

Input device: ZSA Technology Labs Moonlander Mark I Consumer Control
  Type: Mouse
  Identifier: 12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I_Consumer_Control
  Product ID: 6505
  Vendor ID: 12951
  Libinput Send Events: enabled

Input device: ZSA Technology Labs Moonlander Mark I Consumer Control
  Type: Keyboard
  Identifier: 12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I_Consumer_Control
  Product ID: 6505
  Vendor ID: 12951
  Active Keyboard Layout: English (US)
  Libinput Send Events: enabled

Input device: ZSA Technology Labs Moonlander Mark I System Control
  Type: Keyboard
  Identifier: 12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I_System_Control
  Product ID: 6505
  Vendor ID: 12951
  Active Keyboard Layout: English (US)
  Libinput Send Events: enabled

Input device: ZSA Technology Labs Moonlander Mark I
  Type: Keyboard
  Identifier: 12951:6505:ZSA_Technology_Labs_Moonlander_Mark_I
  Product ID: 6505
  Vendor ID: 12951
  Active Keyboard Layout: English (US)
  Libinput Send Events: enabled

[...]

As you see the moonlander is in there multiple times. I wonder if waybar is just listening to the wrong device. And if so, can we specify in the config what device it should listen to? It doesn't seem like it from the docs.

ismay avatar Jun 06 '23 10:06 ismay

Might be related to this: https://github.com/Alexays/Waybar/issues/2082, https://github.com/Alexays/Waybar/issues/2137

ghost avatar Jun 06 '23 10:06 ghost

The keyboard-state module was invisible/broken until today, I just noticed that it isn't working correctly for me either; I detest the physical Caps Lock key because 99% of the time I hit it unintentionally, so I've remapped that key to be Left Control, and I toggle Caps Lock by pressing both Shift keys at the same time, using the Sway config input "type:keyboard" xkb_options "shift:both_capslock". The keyboard-state module does not respond when I toggle Caps Lock like this.

krompus avatar Jun 12 '23 11:06 krompus

The keyboard-state module was invisible/broken until today, I just noticed that it isn't working correctly for me either; I detest the physical Caps Lock key because 99% of the time I hit it unintentionally, so I've remapped that key to be Left Control, and I toggle Caps Lock by pressing both Shift keys at the same time, using the Sway config input "type:keyboard" xkb_options "shift:both_capslock". The keyboard-state module does not respond when I toggle Caps Lock like this.

Same here, if you change using both shifts it will not update, unless you tap caps lock. So I guess the update is hardcoded to the capslock key

ilightwas avatar Aug 09 '23 20:08 ilightwas

Hi all, I'm the one who changed the keyboard-state module recently, if you have any questions, please ask me. In the last change, I introduced libinput for better interaction, but I didn't realize that it caused the bugs you encountered above.

First of all, I'm going to submit a patch to fix the problem that @krompus encountered.

And @ismay , can you provide me the result after running sudo libinput debug-events --show-keycodes with Caps Lock?

asas1asas200 avatar Aug 18 '23 16:08 asas1asas200

Hi @asas1asas200, yeah as long as it's not waybar specific I'd be happy to help (I'm no longer using waybar). This is the output:

-event2   DEVICE_ADDED            Power Button                      seat0 default group1  cap:k
-event1   DEVICE_ADDED            Power Button                      seat0 default group2  cap:k
-event0   DEVICE_ADDED            Sleep Button                      seat0 default group3  cap:k
-event3   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I seat0 default group4  cap:k
-event4   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I System Control seat0 default group4  cap:k
-event5   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I Consumer Control seat0 default group4  cap:kp scroll-nat
-event6   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I Keyboard seat0 default group4  cap:k
-event7   DEVICE_ADDED            Logitech MX Vertical              seat0 default group5  cap:kp left scroll-nat scroll-button
-event9   DEVICE_ADDED            Eee PC WMI hotkeys                seat0 default group7  cap:k
-event3   KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event3   KEYBOARD_KEY            +0.125s	KEY_CAPSLOCK (58) released
 event3   KEYBOARD_KEY            +1.225s	KEY_CAPSLOCK (58) pressed
 event3   KEYBOARD_KEY            +1.337s	KEY_CAPSLOCK (58) released

ghost avatar Aug 18 '23 16:08 ghost

Hi @asas1asas200, yeah as long as it's not waybar specific I'd be happy to help (I'm no longer using waybar). This is the output:

-event2   DEVICE_ADDED            Power Button                      seat0 default group1  cap:k
-event1   DEVICE_ADDED            Power Button                      seat0 default group2  cap:k
-event0   DEVICE_ADDED            Sleep Button                      seat0 default group3  cap:k
-event3   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I seat0 default group4  cap:k
-event4   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I System Control seat0 default group4  cap:k
-event5   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I Consumer Control seat0 default group4  cap:kp scroll-nat
-event6   DEVICE_ADDED            ZSA Technology Labs Moonlander Mark I Keyboard seat0 default group4  cap:k
-event7   DEVICE_ADDED            Logitech MX Vertical              seat0 default group5  cap:kp left scroll-nat scroll-button
-event9   DEVICE_ADDED            Eee PC WMI hotkeys                seat0 default group7  cap:k
-event3   KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event3   KEYBOARD_KEY            +0.125s	KEY_CAPSLOCK (58) released
 event3   KEYBOARD_KEY            +1.225s	KEY_CAPSLOCK (58) pressed
 event3   KEYBOARD_KEY            +1.337s	KEY_CAPSLOCK (58) released

@ismay The results from libinput don't seem to have any problems, I can't troubleshoot your problem at the moment, if you still want to try to fix it then contact me.

Sincerely,

asas1asas200 avatar Aug 20 '23 00:08 asas1asas200

@asas1asas200 Exactly same problem as OP describes. Vanilla waybar config, no keys being swapped. An update broke something.

I introduced libinput for better interaction

Maybe this is the issue, given that:

$ libinput
Command 'libinput' not found, but can be installed with:
sudo apt install libinput-tools

Using latest Ubuntu.

Friptick avatar Sep 21 '23 09:09 Friptick

@Friptick Which WM does you use. Most wayland compositors use libinput backend, such as wlroots and weston, but it is not required. The libinput command in shell cannot indicate your compositor doesn't use libinput, the command is just a client tool of libinput.

asas1asas200 avatar Sep 21 '23 09:09 asas1asas200

OK thanks for the explanation @asas1asas200. Using sway. What should I try?

Friptick avatar Sep 21 '23 10:09 Friptick

You can install libinput-tools or goto /usr/include/linux/input-event-codes.h to find event code. And build waybar from source or wait for the update then change the config to customize your num/caps/scroll lock trigger key.

asas1asas200 avatar Sep 21 '23 10:09 asas1asas200

wait for the update then change the config to customize your num/caps/scroll lock trigger key

To be clear, I don't want to customize the key, I'm using the caps lock key as normal, with normal waybar config. So it does seem to be a straight-up bug. Do you mean a fix is coming in the update?

Friptick avatar Sep 21 '23 10:09 Friptick

What the result does your sudo libinput debug-events --show-keycodes show. (Please install the tool and click caps lock)

asas1asas200 avatar Sep 21 '23 10:09 asas1asas200

$ sudo libinput debug-events --show-keycodes
-event4   KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event4   KEYBOARD_KEY            +0.168s	KEY_CAPSLOCK (58) released

Friptick avatar Sep 21 '23 11:09 Friptick

Using Wayfire, and this happens periodically. Restarting my session doesn't seem to fix it. It seems to stick at least until I reboot. Also using uwsm to launch my session.

> sudo libinput debug-events --show-keycodes
-event1   DEVICE_ADDED            Power Button                      seat0 default group1  cap:k
-event0   DEVICE_ADDED            Power Button                      seat0 default group2  cap:k
-event5   DEVICE_ADDED            Apple Inc. Magic Keyboard with Numeric Keypad seat0 default group3  cap:k
-event8   DEVICE_ADDED            Logitech MX Master 3              seat0 default group4  cap:kp left scroll-nat scroll-button
-event2   DEVICE_ADDED            Blue Microphones Yeti Stereo Microphone Consumer Control seat0 default group5  cap:k
-event5   KEYBOARD_KEY            +0.000s       KEY_CAPSLOCK (58) pressed
 event5   KEYBOARD_KEY            +0.112s       KEY_CAPSLOCK (58) released

kode54 avatar Nov 10 '23 09:11 kode54

@Alexays I think it's fair to reopen this. Several people have confirmed that this is an issue for them as well.

ghost avatar Feb 03 '24 12:02 ghost

I am facing the same issue, but I am using https://github.com/k0kubun/xremap to remap certain keys. However, no function is assigned to the caps lock key.

Without xremap (it works):

-event6   KEYBOARD_KEY            +8.881s	KEY_CAPSLOCK (58) pressed
 event6   KEYBOARD_KEY            +8.934s	KEY_CAPSLOCK (58) released

With xremap (doesn't):

 event11  KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event11  KEYBOARD_KEY            +0.069s	KEY_CAPSLOCK (58) released

paolomainardi avatar Feb 28 '24 13:02 paolomainardi

Thanks @Alexays

paolomainardi avatar Feb 28 '24 14:02 paolomainardi

I'm having a similar Issue, for me it's never updating the state, no matter what I do. libinput output:

-event1   DEVICE_ADDED            Power Button                      seat0 default group1  cap:k
-event0   DEVICE_ADDED            Power Button                      seat0 default group2  cap:k
-event4   DEVICE_ADDED            Razer Razer Ornata V3             seat0 default group3  cap:k
-event14  DEVICE_ADDED            Razer Razer Ornata V3             seat0 default group3  cap:kp scroll-nat
-event16  DEVICE_ADDED            Razer Razer Ornata V3             seat0 default group3  cap:kp left scroll-nat scroll-button
-event7   DEVICE_ADDED            Razer Razer Viper Ultimate Dongle seat0 default group4  cap:p left scroll-nat scroll-button
-event13  DEVICE_ADDED            Razer Razer Viper Ultimate Dongle seat0 default group4  cap:kp scroll-nat
-event19  DEVICE_ADDED            Razer Razer Viper Ultimate Dongle seat0 default group4  cap:k
-event4   KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event4   KEYBOARD_KEY            +0.067s	KEY_CAPSLOCK (58) released
 event4   KEYBOARD_KEY            +0.179s	KEY_CAPSLOCK (58) pressed
 event4   KEYBOARD_KEY            +0.242s	KEY_CAPSLOCK (58) released
 event4   KEYBOARD_KEY            +1.306s	KEY_NUMLOCK (69) pressed
 event4   KEYBOARD_KEY            +1.367s	KEY_NUMLOCK (69) released
 event4   KEYBOARD_KEY            +1.495s	KEY_NUMLOCK (69) pressed
 event4   KEYBOARD_KEY            +1.561s	KEY_NUMLOCK (69) released
 event4   KEYBOARD_KEY            +1.931s	KEY_SCROLLLOCK (70) pressed
 event4   KEYBOARD_KEY            +1.979s	KEY_SCROLLLOCK (70) released
 event4   KEYBOARD_KEY            +2.086s	KEY_SCROLLLOCK (70) pressed
 event4   KEYBOARD_KEY            +2.149s	KEY_SCROLLLOCK (70) released

Schoggi0815 avatar May 28 '24 11:05 Schoggi0815

I guess following is what is happening (at least with me).

Working

  1. The trigger for the module is CAPS-LOCK.
  2. Waybar infers CAPS LOCK state by some equivalent of reading CAPS LOCK LED's state from /sys/class/leds/ (I guessed this from the behaviour: see below).
  3. Now I have mapped CAPS-LOCK LED's state to secondary input language (Marathi in my case).

So,

Behaviour

  • When CAPS-LOCK is pressed with primay output (English), the module is triggerred, but said LED OFF because I am still using English.

  • When I switch to secondary input language (mapping: both shifts together), the LED turns ON, but the module is NOT triggerred, since CAPS-LOCK was never pressed for switching to the secondary input language.

  • When I switch to the secondary input language (using both shifts together), the LED turns ON. Now, when I press the CAPS-LOCK, the module is correctly triggerred and the icon changes to LOCKED icon state.

  • Reciprocally, when I switch back from secondary to English (hence, turn OFF the CAPS LOCK LED) and then hit CAPS-LOCK, the state icon state gets UNLOCKED.

Solution?

I guess a solution would be for waybar to infer CAPS LOCK's state from the system rather than inferring from LED STATE. I found that under X11, one would achieve that by running xset q. I couldn't find an equivalent for wayland though.

pradyparanjpe avatar Jun 12 '24 16:06 pradyparanjpe

Chiming in to say that I'm seeing this behavior as well. The module correctly detects the state of numlock/capslock when launching, but does not react to key further key activations.

Key press is indeed detected by the system:

sudo libinput debug-events --show-keycodes
-event1   DEVICE_ADDED            Power Button                      seat0 default group1  cap:k
-event0   DEVICE_ADDED            Power Button                      seat0 default group2  cap:k
-event15  DEVICE_ADDED            BenQ ZOWIE BenQ ZOWIE Gaming Mouse seat0 default group3  cap:p left scroll-nat scroll-button
-event16  DEVICE_ADDED            BenQ ZOWIE BenQ ZOWIE Gaming Mouse seat0 default group3  cap:k
-event17  DEVICE_ADDED            ATEN ATEN 2/4-PORT 4K HDMI KVM SWITCH seat0 default group4  cap:k
-event18  DEVICE_ADDED            ATEN ATEN 2/4-PORT 4K HDMI KVM SWITCH seat0 default group4  cap:p left scroll-nat scroll-button
-event19  DEVICE_ADDED            ATEN ATEN 2/4-PORT 4K HDMI KVM SWITCH Keyboard seat0 default group4  cap:kp scroll-nat
-event20  DEVICE_ADDED            ATEN ATEN 2/4-PORT 4K HDMI KVM SWITCH seat0 default group4  cap:p left scroll-nat calib
-event19  KEYBOARD_KEY            +0.000s	KEY_CAPSLOCK (58) pressed
 event19  KEYBOARD_KEY            +0.123s	KEY_CAPSLOCK (58) released

This is the module configuration, showing the the correct device is expliticly listed under device-path:

   "keyboard-state": {
       "numlock": true,
       "capslock": true,
       "format": "{name} {icon}",
       "format-icons": {
           "locked": "",
           "unlocked": ""
       },
       "device-path": "/dev/input/event19"
   },

ossimark avatar Aug 04 '24 12:08 ossimark

I am experiencing the same on FreeBSD 14.2 under Sway.

I have noticed that the module does update the state of the Lock keys but only after you press at least two different lock keys (e.g. caps lock, and num lock).

I will try to look into the source code of waybar-keyboard-state module. The breaking change must have been happened when the "interval" property has been deprecated in favour of event polling via libevdev.

achkasov avatar Feb 20 '25 16:02 achkasov

I'm also having this problem. I couldn't find a solution so instead I put together this custom module.

config:

    "custom/keyboard-state": {
        "interval": 1,
        "exec": "$HOME/.config/waybar/keyboard-state.py",
        "return-type": "json",
        "format": "{}",
        "hide-empty-text": true
    },

keyboard-state.py:

#!/usr/bin/python3

syscaps = open('/sys/class/leds/input4::capslock/brightness')
sysnum = open('/sys/class/leds/input4::numlock/brightness')
sysscroll = open('/sys/class/leds/input4::scrolllock/brightness')

capslock = bool(int(syscaps.read()))
numlock = bool(int(sysnum.read()))
scrolllock = bool(int(sysscroll.read()))

syscaps.close()
sysnum.close()
sysscroll.close()

text = ""
if capslock:
    text += " C "
if numlock:
    text += " N "
if scrolllock:
    text += " S "

print(f'{{"text": "{text}"}}')

elidoz avatar Apr 21 '25 11:04 elidoz

Thanks for sharing, @elidoz

Not gonna lie, personally I prefer to continue doing without capslock status than to have a Python script running at a 1 second interval.

Maybe this will serve as inspiration to the maintainers for a native fix.

Friptick avatar Apr 21 '25 23:04 Friptick

I use Waybar with Hyprland and here's my current solution.

waybar config

"custom/capslock": {
  "exec": "~/capslock.sh",
  "format": "{}",
  "interval": "once",
  "return-type": "json",
  "signal": 1
}

capslock.sh

#!/bin/bash

capslock=$(cat /sys/class/leds/input*::capslock/brightness | head -c 1)

if [[ "${capslock}" == "1" ]]; then
  echo '{"class": "locked", "text": ""}'
else
  echo '{"class": "unlocked", "text": ""}'
fi

hyprland.conf

bindirt = , Caps_Lock, exec, pkill -SIGRTMIN+1 waybar

style.css

#custom-capslock.locked {
  background: rgba(0, 255, 0, 1);
}

codestothestars avatar Apr 22 '25 00:04 codestothestars

On Mon Apr 21, 2025 at 4:54 AM PDT, elidoz wrote:

elidoz left a comment (Alexays/Waybar#2215)

I'm also having this problem. I couldn't find a solution so instead I put together this custom module.

config:

    "custom/keyboard-state": {
        "interval": 1,
        "exec": "$HOME/.config/waybar/keyboard-state.py",
        "return-type": "json",
        "format": "{}",
        "hide-empty-text": true
    },

keyboard-state.py:

#!/usr/bin/python3

syscaps = open('/sys/class/leds/input4::capslock/brightness')
sysnum = open('/sys/class/leds/input4::numlock/brightness')
sysscroll = open('/sys/class/leds/input4::scrolllock/brightness')

Still not much better than the built-in module, if it can't auto detect the input# device path to use, since they can change with each reboot or device hotplug.

capslock = bool(int(syscaps.read())) numlock = bool(int(sysnum.read())) scrolllock = bool(int(sysscroll.read()))

syscaps.close() sysnum.close() sysscroll.close()

text = "" if capslock: text += " C " if numlock: text += " N " if scrolllock: text += " S "

print(f'{{"text": "{text}"}}')

kode54 avatar Apr 22 '25 00:04 kode54

That is a pretty elegant fix @codestothestars and I can confirm it works!

For others: instead of the hyprland config, put the following in .config/sway/config:

bindsym --release Caps_Lock exec pkill -SIGRTMIN+1 waybar

Or another SIGRTMIN value as appropriate, just make sure it matches the one in the waybar config.

Thanks @codestothestars for sharing.

Update. Discovered a minor bug: using capslock with shift or control modifier, although nonsensical, does actually change the state. So best add this to config:

bindsym --release Shift+Caps_Lock exec pkill -SIGRTMIN+1 waybar
bindsym --release Control+Caps_Lock exec pkill -SIGRTMIN+1 waybar

Friptick avatar Apr 22 '25 20:04 Friptick