moses-palmer / pynput

Sends virtual input commands
GNU Lesser General Public License v3.0
1.74k stars 244 forks source link

Support connecting to specific X display #516

Closed dp-alvarez closed 1 year ago

dp-alvarez commented 1 year ago

I'd like to use Pynput to control a specific X display given as a parameter. It should be a simple change to (optionally) accept the display string as pass it on to Xlib.

If there is interest in merging this I could work on it.

moses-palmer commented 1 year ago

Thank you for your report.

Does setting DISPLAY not work?

dp-alvarez commented 1 year ago

There are some problems with just setting the variable. One of them is that I'd like to control a given display while displaying a GUI on the "real" one, so this approach would require constantly shuffling the DISPLAY variable which is really inconvenient. Another problem is when running the application on a headless server (where it connects to remote displays at runtime), Pynput refuses to start because it cannot find the display on startup.

Optionally passing the DISPLAY variable would be a simple backwards compatible change, along with deferring the display check for when the controller is actually created.

I can send in a PR if you want to take a look at it.

moses-palmer commented 1 year ago

I started work on this feature back in 2016, and published it just now on fixup-xorg-multiple-displays. At the moment I cannot remember what prevented me from completing the feature, but I can see at least one problem: the backend detection relies on DISPLAY being set to detect whether an X server is running, and thus that the Xorg backend can be used.

dp-alvarez commented 1 year ago

I wasn't thinking about listeners (as I haven't used them for now), so I didn't even consider it would take more work. For the Controller it would be as simple as passing the display to the constructor.

About the backend detection, it tries to connect to $DISPLAY at import time to check that there is actually a display running, but that could be deferred to when the Controller is created instead. If the display can be specified at runtime there is no way to check it exists at import time.

I can send in a PR that implements multiple displays for the Controller, but I'm not sure I will have to time to do the same for the Listener. Having only the Controller supporting multiple displays is better than having no support at all I guess, but up to you if you want to merge it.

moses-palmer commented 1 year ago

Thank you for your offer! I would very much appreciate if you could implement display selection for listeners and controllers on top of the branch mentioned above and verify that the functionality matches your needs. It should just be a matter of accepting a platform specific option to the constructors and propagate it accordingly.

What to do about the module level check required a bit more thought, since not raising ImpoetError when no display can be opened would change the public API.

dp-alvarez commented 1 year ago

I haven't been able to take a look at this yet, will close for now and reopen once I have the time