lan-mouse icon indicating copy to clipboard operation
lan-mouse copied to clipboard

Add raw evdev input emulation

Open samvv opened this issue 7 months ago • 11 comments

This pull request adds another input emulation backend that uses evdev to create a virtual mouse/keyboard, bypassing Wayland restrictions. It is meant to be a fallback for the other Linux backends.

This backend successfully fixes input emulation issues on COSMIC and potentially other platforms that lack a proper remote desktop portal.

Limitations

Currently this feature requires lan-mouse to be run as root, e.g. with sudo -E lan-mouse. This is a temporary limitation that I hope to alleviate by creating a separate daemon and authentication mechanism.

To Do

  • [x] Discrete scrolling needs to be tested. I just put a formula I thought might work. If I'm correct this is a Mac feature, which I don't have.
  • [x] ~A daemon that allows unprivileged execution of lan-mouse, as described above.~ We are going to use an udev rule.
  • [ ] Natural scrolling doesn't work because presumably the WM is responsible for the conversion. We'd need to emulate it. (optional?)

samvv avatar May 29 '25 14:05 samvv

Potentially somewhat related: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2664

samvv avatar May 29 '25 14:05 samvv

@samvv I'm not sure running the daemon as root is going to work. The input capture backends need to be run as the current user to access xdg-desktop portal or the wayland socket. But you can change the permissions on /dev/uinput to allow access to your user. (Steam also does this afaik for controller input)

feschber avatar Jun 01 '25 09:06 feschber

Btw: For the cli backend override to work, you have to add the backend to the config struct as well:

diff --git a/src/config.rs b/src/config.rs
index 41f442d..361bb5e 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -172,6 +172,9 @@ impl From<CaptureBackend> for input_capture::Backend {
 
 #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, ValueEnum)]
 pub enum EmulationBackend {
+    #[cfg(all(target_os = "linux", feature = "evdev_emulation"))]
+    #[serde(rename = "evdev")]
+    Evdev,
     #[cfg(all(unix, feature = "wlroots_emulation", not(target_os = "macos")))]
     #[serde(rename = "wlroots")]
     Wlroots,
@@ -197,6 +200,8 @@ pub enum EmulationBackend {
 impl From<EmulationBackend> for input_emulation::Backend {
     fn from(backend: EmulationBackend) -> Self {
         match backend {
+            #[cfg(all(target_os = "linux", feature = "evdev_emulation"))]
+            EmulationBackend::Evdev => Self::Evdev,
             #[cfg(all(unix, feature = "wlroots_emulation", not(target_os = "macos")))]
             EmulationBackend::Wlroots => Self::Wlroots,
             #[cfg(all(unix, feature = "libei_emulation", not(target_os = "macos")))]
@@ -217,6 +222,8 @@ impl From<EmulationBackend> for input_emulation::Backend {
 impl Display for EmulationBackend {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
+            #[cfg(all(target_os = "linux", feature = "evdev_emulation"))]
+            EmulationBackend::Evdev => write!(f, "evdev"),
             #[cfg(all(unix, feature = "wlroots_emulation", not(target_os = "macos")))]
             EmulationBackend::Wlroots => write!(f, "wlroots"),
             #[cfg(all(unix, feature = "libei_emulation", not(target_os = "macos")))]

I think I might want to remove this duplication at some point

feschber avatar Jun 01 '25 09:06 feschber

Thanks for the information. That steam 'hack' might actually work. At least on Arch it could be as simple as usermod -aG input username.

The daemon I was talking about isn't a lan-mouse daemon, it's this one I just wrote: https://github.com/samvv/input-daemon. It uses polkit to authenticate whatever process connects to it. If I'm correct it should in theory be more secure than the steam hack, where every user process has access (no questions asked), at the price of way more complexity.

What solution would you prefer?

I'll update this pull request with the CLI logic.

samvv avatar Jun 01 '25 11:06 samvv

I just tested and can confirm that adding the group input to the user works!

samvv avatar Jun 01 '25 12:06 samvv

I just tested and can confirm that adding the group input to the user works!

Adding the user to input is not necessary and a much bigger security risk than giving the user access to /dev/uinput via ACLs

feschber avatar Jun 02 '25 09:06 feschber

I'm a bit hesitant to chown the /dev/uinput file. Do you mean that adding the input group is less secure because it allows access to all devices?

If so, what about:

sudo groupadd --system lan-mouse
sudo usermod -aG lan-mouse <username>
echo 'KERNEL=="uinput", GROUP="lan-mouse"' | sudo tee /lib/udev/rules.d/05-lan-mouse.rules

I've just tested this and it works.

samvv avatar Jun 02 '25 17:06 samvv

@sithlord48 May be of interest.

nbolton avatar Jun 02 '25 19:06 nbolton

I'm a bit hesitant to chown the /dev/uinput file. Do you mean that adding the input group is less secure because it allows access to all devices?

Yes, adding the user to input allows arbitrary processes to also read input, which is a much bigger risk.

If so, what about:

sudo groupadd --system lan-mouse
sudo usermod -aG lan-mouse <username>
echo 'KERNEL=="uinput", GROUP="lan-mouse"' | sudo tee /lib/udev/rules.d/05-lan-mouse.rules

I've just tested this and it works.

Sounds like a good solution, if it works!

feschber avatar Jun 03 '25 09:06 feschber

@feschber I've fixed the mouse wheel, at the very least on my setup. We might need to make WHEEL_SENSITIVITY a configuration variable for other setups, but that can happen later.

Is there anything else that needs to be done before this can be merged?

samvv avatar Jun 04 '25 11:06 samvv

As far as I'm concerned, it's looking good! I might even consider moving this backend up in priority for input emulation on systems that have access to uinput. And we might look into a way of automatically setting permissions somehow. But thats something for the future :).

If you fix that formatting error, I would be ready to merge!

feschber avatar Jun 11 '25 11:06 feschber