Trouble with libevdev_grab

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 8 01:21:58 UTC 2024


On Sun, Jan 07, 2024 at 03:35:42PM -0800, Alex Barker wrote:
> Hi,
> 
> I'm having some trouble with libevdev_grab and I am not exactly sure what
> is going on. Basically what happens is when I press enter to start the
> program, the key release seems to get lost and the enter key gets stuck
> until I press the enter key again. The only thing I've come across that
> maybe related was [this](
> https://lists.freedesktop.org/archives/input-tools/2015-December/001228.html)
> old post about needing to drain the fd before passing it to
> libevdev_set_fd.  I am not sure if that's why I seem to be getting a stuck
> key and I have no idea how I should be draining the fd if that is the case.
> I have attached a simple example program that illustrates the issue.
> Hopefully someone can point me in the right direction.


Basically: computers are fast! :)
The sequence that happens here is:
- you press enter
- your program starts
  - program creates a libevdev context
  - program creates a uinput device
  - program grabs the real device
- you release enter
  - because of the grab only your program gets that event

Anything that was listening to the real device would've seen the press
event but not the release, triggering autorepeat.

Your options are using libevdev_get_event_value() to check if any
key is down and waiting for that key/those keys to be released.
Once they are you can libevdev_grab().

Or put a usleep() into your program before libevdev_grab() to wait past
the release if that's all you need to care about right now.

Cheers,
  Peter



> 
> Thanks!
> 
> // gcc libevdev_grab.c -I/usr/include/libevdev-1.0 -levdev
> 
> #include <errno.h>
> #include <fcntl.h>
> #include <libevdev/libevdev.h>
> #include <libevdev/libevdev-uinput.h>
> #include <stdio.h>
> 
> // FIXME switch out for your keyboard device
> #define DEV_PATH
> "/dev/input/by-id/usb-Microsoft_Microsoft_Ergonomic_Keyboard_605519294221-event-kbd"
> 
> int main()
> {
>     int fd = open(DEV_PATH, O_RDONLY | O_NONBLOCK);
>     if (fd < 0) {
>         fprintf(stderr, "Failed to open file: %s\n", DEV_PATH);
>         return 1;
>     }
> 
> 
>     struct libevdev *evdev;
>     int err = libevdev_new_from_fd(fd, &evdev);
>     if (err < 0) {
>         fprintf(stderr, "Failed to create evdev from file descriptor!
> (%d)\n", err);
>         return 1;
>     }
> 
> 
>     struct libevdev_uinput *uinput;
>     err = libevdev_uinput_create_from_device(evdev,
> LIBEVDEV_UINPUT_OPEN_MANAGED, &uinput);
>     if (err < 0) {
>         fprintf(stderr, "Failed to create uinput from device! (%d)\n", err);
>         return 1;
>     }
> 
> 
> //*
>     err = libevdev_grab(evdev, LIBEVDEV_GRAB);
>     if (err != 0) {
>         fprintf(stderr, "Failed to grab evdev! (%d)\n", err);
>         return 1;
>     }
> //*/
> 
>     struct input_event ev;
>     while (1) {
>         int status = -EAGAIN;
>         unsigned int flags = LIBEVDEV_READ_FLAG_NORMAL;
>         do {
>             status = libevdev_next_event(evdev, flags, &ev);
>             if (err == LIBEVDEV_READ_STATUS_SYNC) {
>                 flags = LIBEVDEV_READ_FLAG_SYNC;
>             }
> 
>             if (status != -EAGAIN) {
>                 printf("Event: %d %d %d\n", ev.type, ev.code, ev.value);
>             }
> 
> //*
>             libevdev_uinput_write_event(uinput, ev.type, ev.code, ev.value);
> //*/
>         } while (status != -EAGAIN);
>     }
> 
>     return 0;
> }


More information about the Input-tools mailing list