Skip to content

Instantly share code, notes, and snippets.

@e9x
Last active March 22, 2024 02:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save e9x/f505cf11d42f9470570c9de0b61e15e9 to your computer and use it in GitHub Desktop.
Save e9x/f505cf11d42f9470570c9de0b61e15e9 to your computer and use it in GitHub Desktop.
Qubes redirect mouse input to VM

How it works:

This script will detect the active VM based on the currently focused window and redirect mouse events from DOM0 to the VM until the script is ran again.

This works for games or anything that uses your mouse.

This is basically doing the reverse of how sys-usb makes your mouse available to your entire system.

Based on:

Setup:

  • Install qubes-input-proxy-receiver in the VMs you want to use this in.

    Ideally, you'll install qubes-input-proxy-receiver in a template VM and restart your qubes.

    Fedora based qubes:

    sudo dnf install qubes-input-proxy-receiver
  • Copy the script below to DOM0 and make it executable

    In a networked VM:

    curl -o /home/user/toggle-mouse.sh https://gist.githubusercontent.com/e9x/f505cf11d42f9470570c9de0b61e15e9/raw/b8ce3f1ca4a2fff1c358d14b4811789a58d0a4eb/toggle-mouse.sh

    In DOM0:

    qvm-run --pass-io your-vm "cat /home/user/toggle-mouse.sh" > /home/user/toggle-mouse.sh
    chmod +x /home/user/toggle-mouse.sh

    Make sure to review the script and make sure it's safe.

    cat /home/user/toggle-mouse.sh
  • Configure the script

    Identify your mouse event ID in /dev/input/by-id/

    Make sure your mouse is connected directly to DOM0 and is not in a USB VM

    In DOM0:

    ls /dev/input/by-id/*-event-mouse

    Modify the script to use this mouse

    nano /home/user/toggle-mouse.sh

    Modify this line accordingly.

    local mouse=/dev/input/by-id/usb-Logitech_G203_LIGHTSYNC_Gaming_Mouse-event-mouse
  • Add a keybind to run this script when a key is pressed

    Qubes by default comes with XFCE which you can configure keyboard shortcuts on.

    In DOM0:

    xfce4-keyboard-settings

    Go to "Application Shortcuts", click on "Add"

    Command: /home/user/toggle-mouse.sh

    Press "Ok", then press the key you want to bind it to.

Usage:

You should now be able to open an application that you want to redirect your mouse to, then press the key you binded the script to, then all your mouse events should go directly to the VM instead of DOM0.

Your cursor icon won't be visible, but this could be fixed in the future by spawning swcursor inside the VM while mouse events are being redirected to simulate the cursor icon.

Security:

TODO

#!/bin/bash
get_id() {
local id=$(xprop -root _NET_ACTIVE_WINDOW)
# had to fix this, used to be #{id##* }
local id=${id#*window id # }
echo ${id%%, *} # extract id
}
get_vm() {
local id=$(get_id)
local abc=$(xprop -id $id)
local vm=$(xprop -id $id | grep '_QUBES_VMNAME(STRING)')
local vm=${vm#*\"} # extract vmname
echo ${vm%\"*} # extract vmname
}
main() {
# configure with your mouse event device here
local mouse=/dev/input/by-id/usb-Logitech_G203_LIGHTSYNC_Gaming_Mouse-event-mouse
# this script can be reworked to get the input events from a USB VM and pass them to another VM
# lockfile path
local tmp_file=/home/user/mouse-vm.tmp
# get the active VM
local vm=$(get_vm)
#notify-send "active vm: $vm"
# attempt to detach the mouse if we detect that iwas previously attached
if [ -f "$tmp_file" ]; then
#local attached_vm=$(cat $tmp_file)
#TODO:
#kill -9 $attached_vm
sudo killall input-proxy-sender
rm -- "$tmp_file"
#notify-send "detached mouse from vm, killed $attached_vm"
else
# attach the mouse and save the state to $tmp_file
if [[ -n "$vm" ]]; then
#notify-send "attaching mouse to $vm"
sudo qvm-run -u root --pass-io --localcmd="input-proxy-sender $mouse" $vm "input-proxy-receiver --mouse"&
# TODO: find a normal way to get the pid of the input-proxy-sender that we just spawned
# wait for the qvm-run command to spawn input-proxy-sender then write the pid to a file
#sleep 1; echo "$(pidof input-proxy-sender)" > $tmp_file
# alternatively, we can just create the $tmp_file without any contents and kill every process with the name input-proxy-senedr
touch $tmp_file
fi
fi
}
main
@mooreye
Copy link

mooreye commented Mar 12, 2024

line 43 qvm-run ... for me fails with: open: Permission denied
I assigned my only mouse to mouse var 🫤
I have no USB qube

As a side note, you should always use set -euo pipefail in Bash scripts to catch errors and stop execution of the rest of the script.

@e9x
Copy link
Author

e9x commented Mar 19, 2024

I have no USB qube

This script uses the USB mouse from DOM0, so this is correct.

open: Permission denied

I haven't encountered this on my system. I think the documentation from input-proxy-sender is relevant:

You need to have access to the device file, which most likely means that you need to start input-proxy-sender as root, or you need some udev rule to alter file permissions.

https://github.com/QubesOS/qubes-app-linux-input-proxy?tab=readme-ov-file#input-proxy-sender

I'm not familiar with udev rules, but I think running input-proxy-sender with sudo should fix this.

qvm-run -u root --pass-io --localcmd="sudo input-proxy-sender $mouse" $vm "input-proxy-receiver --mouse"&

@mooreye Are you able to try this?

@mooreye
Copy link

mooreye commented Mar 20, 2024

@e9x
Thanks, it works when I added sudo to input-proxy-sender.
It was also necessary for me to add sudo to killall. Otherwise, it wouldn't detach the mouse.

@e9x
Copy link
Author

e9x commented Mar 22, 2024

Good to hear it worked! I've updated the script to use sudo for starting the input sender and detaching the mouse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment