I am using xbindkeys to bind Alt+left and Alt+right to chvt in order to cycle through virtual terminals, as described here. I modified the arithmetic to be modular with respect to the number of virtual terminals available (six). I launch an xbindkeys daemon for each instance of a window manager (e.g., before starting dwm on tty1 and likewise for openbox on tty2); i.e., each tty has its own xbindkeys instance.

Apparently, xbindkeys can only detect nascent key press events, and not residually held keys. Thus, if I press Alt+right from tty1 to switch to tty2 and then want to continue on to tty3, I must release both keys and re-press both to advance. With non-X ttys, I can either hold both keys or keep Alt depressed while tapping the arrow key. Can this functionality (i.e., key-press memory) be replicated with xbindkeys? Since I apparently need multiple instances (one per WM, as stated), and the program (xbindkeys) appears to detect nascent key press events rather than held keys, it may not be possible. Any workarounds would be appreciated.


To continue with what you have currently developed, you can use the evemu tools package(s) to use the utilities evtest and evemu-event. List the input event devices with sudo evtest and find the line corresponding to your keyboard. I have a special keyboard so I got:

/dev/input/event2:      HID 05f3:0007

Now choose that number (2 in my case) and press the key you want to recognise (Alt for you). I used left shift and got

Event: time 15094562, -------------- SYN_REPORT ------------
Event: time 15094562, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e1
Event: time 15094562, type 1 (EV_KEY), code 42 (KEY_LEFTSHIFT), value 1

We see here I got a type EV_KEY event with code KEY_LEFTSHIFT getting value 1 when I pressed shift, and a similar event with value 0 when I released it.

You can now simply query the state of this key at any time, for example after the chvt. Use, in my case,

sudo evtest --query  /dev/input/event2 EV_KEY KEY_LEFTSHIFT

The return code from this command is 0 if the value is 0, and 10 if the value is 1. You can use echo $? to show this value.

Knowing the state of the key, you can now emulate a keypress event so that the X11 server sees the "current" state. In my case, I would do

sudo evemu-event /dev/input/event2 --type EV_KEY --code KEY_LEFTSHIFT --value 1

As you might imagine, there is probably a simpler solution to your original problem. Instead of using xbindkeys and having this problem fixed here, you might look at a different solution using libevent. There are examples in C in Linux USB Input Subsystem and part 2 in Linux Journal. Your system may have a Python library evdev to make this easier.

  • Thanks for the many suggestions. I will start by having a look at libevent, since it would be nice to use one interface across all ttys, rather than switching between interfaces as I enter/exit X11-enabled ttys. – user001 Oct 31 '17 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.