Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Allow event "consumption" on Linux via evdev #150

Open
hatl opened this issue Jun 14, 2022 · 14 comments
Open

[Feature Request] Allow event "consumption" on Linux via evdev #150

hatl opened this issue Jun 14, 2022 · 14 comments

Comments

@hatl
Copy link

hatl commented Jun 14, 2022

On other platforms, it's possible to consume an event by setting reserved to 1.
Under Linux, this could be done by "grabbing" the device(s) when using evdev.
And then forward events to a new virtual device if reserved is 0.
This solution would work for X11 and Wayland.

What do you think?

BTW: this is how evsieve works

@kwhat
Copy link
Owner

kwhat commented Jun 14, 2022

I am going to need a lot more detail about how this would work. A proof-of-concept would be ideal. If it is possible I don't mind adding it to 1.3 which is currently in progress and overhauls a lot of the Linux code.

@hatl
Copy link
Author

hatl commented Jun 14, 2022

Thanks for the quick reply!
Maybe the evsieve code can serve as a basis.
It seems to work really well.

@kwhat
Copy link
Owner

kwhat commented Jul 1, 2022

Apologies, I thought I responded to this weeks ago but just noticed I never submitted my response.

I've read though the readme and it looks like it is interacting with /dev/input which would require additional permissions and why this library doesn't currently use /dev/input. I'll leave this open for a while and revisit the idea of /dev/input in the future.

@Rush
Copy link

Rush commented Aug 11, 2022

This might also be needed for support of Wayland. Unless Wayland on Linux is not a goal of this project?

@szymonj99
Copy link

I'm also interested in Wayland and dev/input support.
Could this potentially be a configurable option? 👀
Thanks! 💯

@kwhat kwhat added this to the 1.3 milestone Aug 18, 2022
@kwhat
Copy link
Owner

kwhat commented May 1, 2023

After a lot of thought, evdev will be the way forward for both Linux and BSD support. It is going to be a monumental undertaking to implement so if anyone wants to help make this happen, please reach out. I will start look at this again after I finish refactoring a lot of the existing code but I don't think this will make it into 1.3.

@szymonj99
Copy link

Consider this as a bit of a self-plug. I've personally used libevdev to perform input simulation and capturing on Linux as part of my software KVM switch uni project. The repo for that is here (a lot of refactoring can be done with it). Imo, it seemed quite okay to work with, so hopefully it doesn't cause many issues if you decide to implement evdev in the future. 💯

@kwhat
Copy link
Owner

kwhat commented May 4, 2023

I was just looking at libevdev which looks like its going to deal with most of the heavy lifting. The biggest problem I am aware of is that the mouse coordinates are all relative which is both good and bad. I would need to figure out a way to get those relative coordinates mapped on to the desktop environment.

@szymonj99
Copy link

Could that not be performed with a display-server-specific function call for X11 and Wayland? Correct me if I'm wrong 💯

@kwhat kwhat modified the milestones: 1.3, 2.0 Jun 23, 2023
@kwhat
Copy link
Owner

kwhat commented Aug 16, 2023

Do any of you know how to consume events with libevdev? I am working on setting up epoll and event hooking but I have no idea how to prevent event propagation.

@szymonj99
Copy link

The way that I have done it was by calling ::libevdev_grab(input, LIBEVDEV_GRAB) where input is a libevdev*. To get a libevdev*, I used ::libevdev_new_from_fd for each symlink present in /dev/input/by-path that ends with -event-mouse or -event-kbd. If you go down this route, IIRC the device file needs to be kept open until the hook is finished. In a relevant destructor you can then call libevdev_free and close the file descriptor, in that order.
I've not used epoll before and instead used ::libevdev_next_event with the LIBEVDEV_READ_FLAG_BLOCKING as I had this running on a separate thread that I wanted to block.

@kwhat
Copy link
Owner

kwhat commented Aug 22, 2023

@szymonj99 thanks for the info, the only example I've found is this where it kind of proxies what is read to something created with libevdev_uinput_create_from_device after grabbing with libevdev_grab. Is that +/- the correct approach? If so, what happens if the program is run multiple times, do we get a proxy chain that just grows?

@szymonj99
Copy link

When I was working with libevdev, I've never tried running the program multiple times, but I assume it would not be optimal 😆 How the events would get passed along I'm not too sure, but if the libevdev device is grabbed, then I would assume that only the first process that grabs the device would see the events, and they wouldn't be passed further. This would mirror the normal behaviour when a libevdev process grabs the device, and the display server etc. does not see the events.
In my program, I've turned the class responsible for interacting with libevdev into a singleton to avoid usage that could lead to unexpected behaviour. You could use a named semaphore to further prevent issues that could arise when users try running a program multiple times.
IIRC, you only need to call either ::libevdev_from_fd or ::libevdev_uinput_create_from_device, not both. Then you call ::libevdev_grab and that is it. In my program, I used the former and had no issues with it (apart from needing either sudo permissions or for the user to be in a specific input group). Then call ::libevdev_next_event in a loop.

@kwhat
Copy link
Owner

kwhat commented Aug 31, 2023

Good news and bad news.

I've got it things more or less working with libevdev. The bad news is that libevdev_uinput_write_event requires access to /dev/uinput which seems to be owned and grouped to root with 600 permissions. I don't know if this is the standard, or if this is how my distribution does things.

It is pretty easy to override the permissions with a /etc/udev/rules.d/99-libuiohook.rules file containing something like this:

SUBSYSTEM=="misc", KERNEL=="uinput", GROUP="input", MODE="0660"

After running udevadm control --reload-rules && udevadm trigger, /dev/uinput will now be owned by root and grouped to input with mode 0660. This matches the default behavior for /dev/input on my distribution, but again, I don't know how other distributions do these permissions. You may need to add modules="uinput" to /etc/conf.d/modules if it is a module and not loaded by default

If we stick with evdev we would likely need to use one of these udev rules to make permissions more permissive. This isn't the end of the world, but it is definitely inconvenient. I would also need to verify that this solution works on at least a few other distributions. I don't use systemd so there maybe other issues.

Other options. There is libinput which sits a bit further up the stack and does not require any special permissions or udev rules. I believe there are some x11 compatibility here so this makes it an appealing choices when trying to support both environments. Con is that you couldn't use it outside of the window environment like x11 or wayland which was a feature ask at some point.

Thoughts?

@kwhat kwhat added the blocked label Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants