Python - How to get current keylock status?

10,272

Solution 1

└──> xset q | grep LED
  auto repeat:  off    key click percent:  0    LED mask:  00000000
└──> xset q | grep LED
  auto repeat:  off    key click percent:  0    LED mask:  00000001

When the caps lock is on, the LED mask should be 1 and if the LED mask is off, it should be 0.

Additionally since you mentioned that you wanted to use python, you could get the value in the following way

>>> import commands
>>> # Caps Lock is off.
>>> commands.getoutput('xset q | grep LED')[65]
'0'
>>> # Setting Caps Lock on now.
>>> commands.getoutput('xset q | grep LED')[65]
'1'

python 3 version:

import subprocess
if subprocess.check_output('xset q | grep LED', shell=True)[65] == 50 :
    capslock = False
if subprocess.check_output('xset q | grep LED', shell=True)[65] == 51 :
    capslock = True
print( "capslock ON is : ", capslock )

Solution 2

If you can wait a day or two, I'll add this functionality to python-evdev and update this answer. It's probably going to look something along the lines of:

from evdev import InputDevice, ecodes

dev = InputDevice('/dev/input/eventX') # your keyboard device
dev.ledstates(verbose=True)
{ (0, 'LED_NUML')    : True,
  (1, 'LED_CAPSL')   : True,
  (2, 'LED_SCROLLL') : False}

Using xset, as mentioned by @ronak, is a lot easier since you don't have to have read permissions on any input devices. Unfortunately, it works only under X (and X in turn uses the evdev interface (at least on linux)).


Well, It took me long enough, but it's in. The interface for getting 'ON' LEDs ended up being:

>>> dev.leds()
[0, 1, 8, 9]

>>> dev.leds(verbose=True)
[('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_MISC', 8), ('LED_MAIL', 9)]

Getting all available LEDs on a device:

>>> dev.capabilities()[ecodes.EV_LED]
[0, 1, 2]

>>> dev.capabilities(verbose=True)[('EV_LED', ecodes.EV_LED)]
[('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_SCROLLL', 2)]

Solution 3

Ok, after reading the source code for python-keyboardleds and the console_ioctl manpage, here's how to do it in plain Python:

import os
import struct
import fcntl

DEVICE = '/dev/tty'    

_KDGETLED = 0x4B31

scroll_lock = 0x01
num_lock = 0x02
caps_lock = 0x04

fd = os.open(DEVICE, os.O_WRONLY)

# ioctl to get state of leds
bytes = struct.pack('I', 0)
bytes = fcntl.ioctl(fd, _KDGETLED, bytes)
[leds_state] = struct.unpack('I', bytes)

# Use bitmask to check status caps_lock bit
status = leds_state & caps_lock != 0

print "Caps Lock is On: %s" % status

Note: This only works for real terminals and VTs (1-7, those accessible with ctrl+alt+Fx), not for pseudo-terminals in an X11 terminal emulator for example.

To check, run tty in your console:

$ tty
/dev/tty1    # will work

$ tty
/dev/pts/4   # won't work

Using /dev/console as the device to query will work in X11 as well, but requires root privileges.

For details on the concepts involved see the Wikipedia pages on ioctls and bitmasking, and the docs to the Python fcntl module.

Share:
10,272
Admin
Author by

Admin

Updated on June 16, 2022

Comments

  • Admin
    Admin about 2 years

    I'm attempting to write a simple programme that displays the current status of the different keylocks, but I'm unable to find a solution as to how to get the current status of them in Python. Thank you.

  • Admin
    Admin over 11 years
    Thanks! I see that 0 is none, 1 is capslock, 2 is numlock, 4 scroll lock and afterwards it adds up. Great!
  • Admin
    Admin over 11 years
    This looks great! If you don't mind adding that, I love this solution (and the fact that it solves the problem long term)!
  • Admin
    Admin over 11 years
    Thanks, while I won't be using this, I appreciate the example on ioctls. I'll definitely go over this on the weekend!
  • Admin
    Admin almost 11 years
    From the docs, Deprecated since version 2.6: The commands module has been removed in Python 3. Use the subprocess module instead.
  • mszegedy
    mszegedy about 9 years
    Thank you for implementing this, @gvalkov. In today's implementation, it seems that one must use dev.leds() to get a list of active LEDs, each being an int.
  • tweej
    tweej almost 9 years
    There are cases where the keyboard LED does not accurately represent the state of caps lock.