( I hope this becomes visible to search engines so people will find this guide )
The first (and maybe fastest) choice with virtual input using Python is python-uinput
, and it offers a simple example on how to easily move the mouse cursor. [GitHub Repo]
However, that movement is only relative, implied by the REL_X
/REL_Y
names. For the uninitiated, relative means moving the mouse to a position relative to its current location.
In my search to find a way to do absolute mouse movement with this module, I came across these three pages that offered important information on it:
Absolute movement is when your mouse moves to a position relative to an area, as opposed to relative to itself. For example 100,100
is the center of a 200x200
area. In this case, an area will most likely be your monitor.
python-uinput
:First, we have to talk about how “screen space” is calculated on Linux. The whole “screen space” is a rectangle that is just big enough to contain all connected monitors. That means that a setup with one monitor with the size of 1280x720
will have a total “screen space” of 1280x720
. A setup with two monitors, 1366x768
and 1440x900
side-by-side will be 2806x900
. This, of course, changes if you have one monitor on top of another or one monitor is higher than the one next to it etc.
Oh, and keep in mind that y
is counted top-to-bottom (0 at the top and 900 at the bottom).
Now, the important thing to know about python-uinput
that it registers input events on the uinput
device, which includes mouse movement. Quoting from the Launchpad page, “Xorg does not assign mouse handlers for absolute axis devices by default.” That means that we have to do it ourselves, and thankfully, python-uinput
provides a helpful feature:
Line 183 in __init.py__:
absmin, absmax, absfuzz, absflat = ev_spec[2:]
All we have to do is add a tuple to an argument that involves mouse movement events, such as ABS_X
and ABS_Y
:
device = uinput.device([uinput.ABS_X + (0, 255, 0, 0), uinput.ABS_Y + (0, 255, 0, 0)])
The first two numbers in the tuple are the most important for most applications, since they dictate the range for each axis.
How does this tie into the “screen space” thing? The size of the “screen space” is what we can use as a range for ABS_X
and ABS_Y
.
That also means that we can define an area, say in a monitor, by mapping (or scaling) a range 0 to monitor_sizex
to monitor_topleft_x to monitor_topright_x
(same with y). Meaning that 0,0
, is the top-left of the monitor, 1440,900
is the bottom-right and so on. (I will not show an example of that since there are many out there)
ABS_X
and ABS_Y
that correspond to a single 1280x720
display, and moves the mouse to 10,10
. import uinput
import time
device_events = (
uinput.ABS_X + (0, 1280, 0, 0),
uinput.ABS_Y + (0, 720, 0, 0),
)
with uinput.Device(device_events) as device:
time.sleep(1)
device.emit(uinput.ABS_X, 10)
device.emit(uinput.ABS_Y, 10)
Notice that we use time.sleep(1)
before doing anything with the device. That is a weird quirk with uinput where it won’t initialize completely instantly, and we must wait a little bit before doing anything. You can make that delay shorter if you like.
this document was generated with pandoc.