python-evdev icon indicating copy to clipboard operation
python-evdev copied to clipboard

What's the proper way to detect long press on a key

Open wouitmil opened this issue 8 years ago β€’ 4 comments

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

wouitmil avatar Sep 04 '17 18:09 wouitmil

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])

gvalkov avatar Sep 06 '17 21:09 gvalkov

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

wouitmil avatar Sep 07 '17 09:09 wouitmil

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])

gvalkov avatar Sep 07 '17 21:09 gvalkov

πŸ‘πŸΎπŸ‘πŸΎ

kjedamzik avatar Jan 16 '18 19:01 kjedamzik