Send keystrokes to non-active GUI application without occupying the keyboard - python

As the title explain, i'm trying to use the terminal to send commands as keystrokes to a GUI application that's minimized.
There is a lot of similar questions here on Stack with some great answers, but i'm having, mainly, three problems with the solutions i saw: Most of the solutions need the automated application to be the active one. Or, i can't normally use my keyboard while the script/process is running. Or worse, the solution works only on Windows OS.
I need what this person asked 2 months ago: Send keystrokes to a specific window (in background), but do something else in the meantime
But i want it on Linux.
I'm using Kubuntu 18.10, if that helps.
xdotool was close, but i couldn't quite get it to send the commands to a specific window or PID. It also uses "my keyboard", so i can't, for example, write an essay/code/browse online while xdotool is running. Pexpect also have this last problem.
AutoHotKey looks like it would work, but it's only for Windows and i'm trying to not use Wine. Same with pywin32.
keyboard (https://github.com/boppreh/keyboard) seems nice, but it can't send a command to a specific application. Same with PyAutoGUI.
I selected the Python tag because most of the solutions i saw use Python, but i'm open to any language.

Use a nested X server to input keystrokes without changing focus or keyboard grab.
Proof of concept:
Xephyr -resizeable :13
export DISPLAY=:13
xterm
xdotool type rhabarber
The Xephyr nested X server is started and will listen on local X socket 13 (whereas :0 typically identifies the currently running X server, but when multiple sessions are ran concurrently, it could be higher).
Then we set DISPLAY environment variable to :13, so any X application we start will connect to Xephyr; xterm is our target application here. Using xdotool or any other tool we can send keystrokes.
As the target X server is identified through $DISPLAY, applications can be started or input events triggered from elsewhere as well. If needed, you might also run a lightweight window manager within Xephyr, e.g. to 'maximize' the application so that it fills the whole Xephyr window.

Related

Python - control application started by the different user in Windows

I am making application that controls a browser with SendKeys. But as SendKeys get the full control over the keyboard, I want to run this app under the different user. This way I will be working, the application will do what it have to do, and we will not make problems for each other).
The simplest code is
import time
import SendKeys
time.sleep(10)
SendKeys.SendKeys('hello')
I run it, focus on the field where I want to insert my text "hello", and wait. If I don't change the user, all is done as expected.
But when I run it, change the user and return after 10 seconds, I see that SendKeys sent nothing to the program.
How to send keystrokes to the program under the different user?
(I was trying to do the same with pywinauto, but the result was almost the same - all is good if I don't change the user, and error if I change it. So I thought that it is much simplier to resolve this problem with only SendKeys).
Just to summarize our discussion in comments and in the chat. Your wishes are very wide. I'm just trying to show you some directions to learn.
If you want to use SendKeys/TypeKeys/ClickInput methods (working as a real user), you need to run your automation script in the remote session, not locally. This is explained in details in my other answer: SetCursorPos fail with "the parameter is incorrect" after rdp session terminated.
If you want to run the automation on the same machine silently (in minimized state), there is an example for dealing with hidden windows: Python - Control window with pywinauto while the window is minimized or hidden. Just minimize the window and use silent methods (almost all except ClickInput and TypeKeys).
Feel free to ask more detailed questions about pywinauto and GUI automation.

Bring terminal to the front in Python

Is there a way to bring the Linux terminal to the front of your screen from a python script? Possibly using some kind of os. command
I.e - Your python script opens up a GUI that fills the screen, but if a certain event happens that you want to see printed in the terminal to be viewed, but don't want to / can't show this information on the GUI (so please don't suggest that)
And if possible, hide it back behind your other windows again, if needed.
(Python 2, by the way)
Any suggestions greatly appreciated.
Not in any generally supported way.
Some terminal applications may support the following control sequences. However, these sequences are not standardized, and most terminals do not implement them.
\e[5t - move window to front
\e[6t - move window to back
\e[2t - minimize ("iconify") window
\e[1t - un-minimize window
— from http://rtfm.etla.org/xterm/ctlseq.html
That "bring the Linux terminal to the front of your screen" is likely talking about terminal emulators running in an X Window environment. Ultimately this is accomplished by making a request to the window manager. There is more than one way to do this.
xterm (and some other terminal emulators) implement the Sun control sequences for window manipulation (from the 1980s) which were reimplemented in dtterm during the early 1990s. xterm has done this since 1996 (patch #18).
Python: Xlib — How can I raise(bring to top) windows? mentions wmctl, a command-line tool which allows you to make various requests to the window manager.
xdotool is another command-line tool which performs similar requests.
finally, Can a WM raise or lower windows? points out that you can write your own application (and because python can use shared libraries written in C, you could write a script using the X library).

Is it possible to get current application running with python script

I am very much concerned about my productivity all the time. I have recently come across this beautiful chrome extension Limitless
But this is only measuring what i'm doing within the chrome application. As I work most of the time with pdfs, videos etc, I want to develop similar application for linux(ubuntu) desktop enviroment.
Basically I want the script to run continuously as long as the workstation is on.
It should be able to know what I'm currently looking at (for eg a pdf file or a lecture video in vlc) and get the name of the respective file, start time, end times etc and finally post to db.
It is better if it could know if the system is idle or at sleep.
I don't have slightest clue at bash scripting. so my questions is could this task be accomplished with python.
What I've tried?
I started with a search in google "get current application python", "current window title python" etc etc and really surprised to see absurd results.
Please give me pointers on this.
I think you are asking for vocabulary. So I give you what I know.
You are using Ubuntu so your Window Manager may be Gnome.
The window manager knows which window has the focus.
So maybe you want to find out which window has the focus and you want to map it to the Process that opened the window.
What you need to focus on is is module for Python or a Python Binding for the window manager. This module is likely to also be able to control the windows.
The window manager is started with startx.
You could try to call a command line tool and catch the results
How do get the process list on command line:
https://stackoverflow.com/questions/53489/how-do-you-list-all-processes-on-the-command-line-in-windows
And how to call a tool with python:
Python subprocess.call and subprocess.Popen stdout
[edit] Repeating the call in Intervals and counting the intervals a process were running gives you a good estimation of running time of a process...
[edit2] As GreenAsJade said, you search a way to find out which windows has the focus.
See How do I detect the currently focused application?

Duplicate device input events on unix (/dev/input/event)

I'm using linux/ubuntu, and I would like to play a little bit with my touchpad. I'm trying to use python-evdev to read events from /dev/input/events, for now just printing them:
import evdev
dev = evdev.InputDevice('/dev/input/event6')
import time
while True:
try:
for event in dev.read():
print event
except:
print " ~ "
time.sleep(.5)
If I do run that script in with root privilege in a virtual console (outside X, pressing ctrl+alt+F1), the script does print events when I touch the touchpad. Yet, if X is on screen and I run this in a gnome-terminal console, nothing is printed; I somehow guess this is normal, the inputs are intercepted by X. Yet I would like to get them anyway. Is there a way to duplicate whatever comes from /dev/input/event6 so thqt both X and my script can read all events ?
sorry, a bit late on the answer here.
Up until version 1.8, the xorg synaptics driver used the EVIOCGRAB ioctl to prevent events to be delivered to other clients. That's disabled now by default, you can still use the GrabEventDevice option to disable it on your machine for older versions (see man synaptics).
In short, nothing wrong with your script, it's the synaptics driver that's the problem here. You'll find that your script will work on other devices just fine (though the xorg wacom driver did also grab the device until recently).
upstream commit in synaptics:
http://cgit.freedesktop.org/xorg/driver/xf86-input-synaptics/commit/?id=f1948e08ee9894864254a18098e4f4fceb6e322f
So, your idea is, X got the data from your touchpad, so that your python code is blocked from receiving touchpad signal, right? Or, may I repeat your words as: at least for some specific kind of device, an application can't get /dev/input/event*, when another is reading from that device?
Theoritically, since linux make all devices as a file, you are accessing a file as read-only, while X is also read-only accessing the file.
I just did another experiment as: I have a infrared reciver on my archlinux, and I connected to the system in two ssh consoles. I use two ways to access IR, that is, two applications to read the file of /dev/input/event0 (event0 is the SF on my arch):
1, a piece of python code, with evdev;
2, a shell command as: sudo cat /dev/input/event0 | hexdump
You can look on the 2nd as working as your X. If you were reasoning correctly, they both should not receive data from the IR (event0) on the same time, when I sending signal from a IR remote controller, right? But, I really got date on the two ssh consoles(I wish I could post image, but I am new with too low reputation to do so).
So, I think it should not be the reason. I guess it might be because of your touchpad itself. You know, some devices can only work on a single application. e.g., keyboard can only enter characters on the active application, and some input method just make itself as active over other applications, and redirect after it processed. Also, say, if you had a VM running on your system, and you use only one mouse, what would happen if you are moving pointer on the host desktop? Will the pointer in VM move? Or vice versa?
So I need more info about your touchpad. If your TP works only with a single active applicatio, I am afraid you need somethink like a hook to get touchpad signal ahead of X, and redirec it to X and your python code, which might be beyond evdev.
You could create a kernel input handler based on evdev so that the device input is distributed both to the normal /dev/input/eventN and, let's say, /dev/input/copied_eventN
X would read from /dev/input/eventN but you would still be able to read from /dev/input/copied_eventN
Actually you could very easily create a kernel module by copy-pasting the code in drivers/input/evdev.c

Python Send Keystrokes to Non-Active Application

I'm automating some common GUI tasks I have to do in an application, and I'm using a Python program and SendKeys to do it. So far I've had to activate the application I'm sending keys to (since SendKeys just sends the keystrokes to the active window), but I'd like to be able to send keystrokes to an application in the background. Is there a way to do that, or am I dreaming an impossible dream?
Thanks for your help.
pywinauto is another MS-only GUI automation tool, this one written in Python.
SendKeys is a Python module for Windows that can send one or more keystrokes or keystroke combinations to the active window.
If you need to do some automated work in the background, make another user/session and do it in that.
However if you must do something of this like on windows, I always reach for autoit.
It's M$ only and perfectly suited to automating tasks on that OS.
This is a frequent question in the autohotkey.com forums. Search under
"sending commands to controls". Basically, if you have the control ID, then it doesn't need to be visible in order to operate on it. There're more details on the forums.
good luck!

Categories

Resources