What's the proper way to detect long press on a key
Hi,
For a linux embed project, we need to detect long press on a keys. Is it possible from scratch in evedv? If not, how would you manage it?
Kind regards
Hello @wouitmil
You could look for key events with a value of 2. The key event values are: 1 for key press, 0 for key release and 2 for when a key is being held. You can easily see this by running python -m evdev.evtest.
So, you can start with something like:
from evdev import *
from select import select
device = InputDevice('/dev/input/event2')
for event in device.read_loop():
if event.type == ecodes.EV_KEY and event.value == 2:
print('%s is being held' % ecodes.KEY[event.code])
Thanks Gvalkov,
I've already found this. But My issue is to find the duration of the keypress. I suppose I've to save the KeyPress timestamp and KeyRelease one and make a difference. But I was wondering if there was a a built in function for this purpose
There's nothing builtin, I'm afraid - python-evdev just exposes what evdev provides. Here's another way to detect held keys (using select() and a timeout):
from evdev import *
from time import time
from select import select
dev = InputDevice('/dev/input/event2')
def detect_key_hold(hold_time_sec=0.5):
state = {}
while True:
# Block for a 100ms or until there are events to be read.
r, _, _ = select([dev], [], [], 0.1)
if r:
for event in dev.read():
if event.type == ecodes.EV_KEY:
# When the key is pressed, record its timestamp.
if event.value == 1:
state[event.code] = event.timestamp(), event
# When it's released, remove it from the state map.
if event.value == 0 and event.code in state:
del state[event.code]
# Check if any keys have been held for longer than hold_time_sec seconds.
now = time()
for code, ts_event in list(state.items()):
ts, event = ts_event
if (now - ts) >= hold_time_sec:
del state[code] # only trigger once
yield event
continue
for event in detect_key_hold():
print('%s is being held' % ecodes.KEY[event.code])
ππΎππΎ