Is it possible to close a window in macOS with Python? - python

Actually, I wanna do some automated operations on macOS, like closing a specific window.
I have read some threads, and I got know about Appkit and Quartz from How can I minimize/maximize windows in macOS with the Cocoa API from a Python script?.
Here below is my current progress:
import AppKit
for app in AppKit.NSWorkspace.sharedWorkspace().runningApplications():
if app.localizedName() == 'Google Chrome':
app.hide()
With AppKit, I can hide a specific application successfully. But there are two issues for me with this method: first, it seems that AppKit can only manage Applications, but not Windows (i.e., the above code hides all Google Chrome windows at once); besides, AppKit seems to be only able to Hide an application, but not Quitting it or Closing it.
I also tried Quartz. With the below code, I can successfully find the specific windows that I wanna control, especially with the characteristic kCGWindowNumber. But I would like to ask, is there any module that can allow me to close (or hide) the window, maybe like with the kCGWindowNumber?
import Quartz
for window in Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID):
if window['kCGWindowOwnerName'] == "Google Chrome" and window['kCGWindowLayer'] == 0:
print(window)

Related

Tkinter Toplevel window and multiple workspaces - place window in originating linux workspace

I run this on Debian Gnome, but I think this is relevant for most UNIX distributions and interfaces:
from time import sleep
from Tkinter import Tk,Toplevel
tk=Tk()
def run():
sleep(3)
Toplevel(tk)
run()
In Gnome, running this and switching a workspace will cause the Toplevel window to appear in your current workspace, instead of the one that actually runs the command. Is there a way to fix this so the new window appears where the command runs? If this is a Gnome specific thing let me know and I'll amend the question and tags.
To be clear: I have an app that can pop these windows up on it's own while working - and I'm doing other things. The sleep in the above is there to emulate that.
This makes sense it would work this way, but I'm wondering if there is any easy bypass? I have an application using Toplevels as "patience, running" windows, and it's annoying when they appear in different workspaces.

better way to automate mouse&keyboard using pyautogui

I wrote a script using pyautogui that should start an program (an IDE) and then start using it.
This is the script so far:
#! python3
# mouseNow.py - Displays the mouse cursor's current position.
import pyautogui, sys, subprocess
from time import sleep
x,y = 1100,550
subprocess.call([r'C:\...exe', arg1, arg2])
pyautogui.click(x,y)
sleep(5) # 2 sec should suffice but this is for safety
pyautogui.typewrite(my_string)
pyautogui.press('enter')
This works well but I want to be portable. The x,y values were determined by where the program prompt appears on screen after I start the program, but this is not portable, I think. Is there a way to point the mouse to the prompt without giving const parameters? something like move_mouse_to_window_of_this_process_after_starting_it()
Also, I use sleep() so I would write the data to the window after it appears, but I guess it's not a good way (some PC will run this much slower, I guess), so is there a way to know when the prompt appeared and then do the pyautogui.typewrite(my_string)?
EDIT: I found a simple solution for the move_mouse_to_window_of_this_process_after_starting_it()
:
>>> pyautogui.hotkey('alt', 'tab')
If you need portable and reliable solution, you have to find a library that supports accessibility technologies to access GUI elements by text. Basic technologies are:
Win32 API, MS UI Automation (Windows)
AT-SPI (Linux)
Apple Accessibility API (MacOS)
There are several open-source GUI automation libraries supporting some of these technologies (usually 1 or 2). Python solutions:
pywinauto on Windows (both Win32 API & MS UIA, see Getting Started Guide)
pyatspi2 on Linux
pyatom on MacOS
There is also a thread on StackOverflow regarding hard sleeps vs flexible waiting.
Enjoy! :)
The way you are interacting with the .exe excludes alternatives to coordinates or blind firing (Tab, Tab, Enter etc..).
If the application has an API, you could interact with it programatically.
If it doesn't you can only try to match the location for x screen resolutions, and this only if the GUI is used in Fullscreen/windowed Fullscreen.

SendKeys method of AutoIT, shell script or pywinauto lib is not working

Scenario is, I want to handle IE pop up in robot framework with python. To handle pop up, I used AutoIT SendKeys, shell script, pywinauto TypeKeys.
The code is working properly when running on a local machine but when I run the script through team city on the agent machine, then it fails.
My observation is that in the agent machine the code is not working to handle the windows pop up.
After analysis, I have found that this is because the agent machine is working as a locked system while running script through team city.
Code:
def fhandle_savepopup(self):
shell = win32com.client.Dispatch("WScript.Shell")
seleniumLib = BuiltIn().get_library_instance('Selenium2Library')
shell.AppActivate ("Internet Explorer")
sleep(2)
autolib = BuiltIn().get_library_instance('AutoItLibrary')
shell.SendKeys('{F6}')
sleep(3)
shell.SendKeys('{TAB}')
sleep(3)
shell.SendKeys('{ENTER}')
I used AutoIT and pywinauto lib too. But no luck.
Please help me find a solution for this.
You need to keep your desktop open and non-locked (it can be solved by setting auto-logon up + VNC session like TightVNC). For TightVNC you might also require video card drivers update and set custom resolution (in NVIDIA control panel, for example). Of course this node must be connected to the Team City master node from this open desktop (not as a service).
Another option is to click window buttons silently (without real user input emulation). In pywinauto it can be done using Click() (ClickInput() is more realistic and won't work for locked system):
app.Window_(title="Popup title").Wait('visible', timeout=10)
app.Window_(title="Popup title").OK.Click()
P.S. TypeKeys() also works as a real user input. We have plans to implement silent version (SendChars) using WM_CHAR window message that might work for you. But pywinauto 0.6.0 release is currently in deep re-factoring. So it might be released in April or even May, but with great WPF support.

How do I control a non-browser window that is part of Firefox?

I'm on OSX using Python 2.x, Selenium & Firefox
I'm automating testing a javascript webapp with Python & Selenium.
One of the links (Add File) in the application opens up a non-browser firefox window titled "File Upload" which looks like (/is?) a Finder window.
Is there a way that I could locate and control this window from my python script? I know Selenium can't do it, but I wondering if it might be possible with something like 'import applescript' and if so how?
I found atomac which allows me to control mac apps through their accessibility controls (which needed to be enabled on Mavericks for Aptana in System Preferences -> Security & Privacy -> Privacy -> Accessibility). Cool tool, but the documentation is pretty sparse. The examples provided on the page above got me to the point where I could close the window via the cancel button, but I had to review the function definitions in atomac's AXClasses.py to figure out the rest. Here's the solution.
import atomac, time
from atomac.AXKeyCodeConstants import *
# to allow me to make firefox frontmost while testing
time.sleep(5)
# get a reference to the running app
firefox = atomac.getAppRefByLocalizedName('Firefox')
# get the window of the reference
firefoxwindow = firefox.windowsR()[0]
# send key sequence to go to my home folder
firefoxwindow.sendKeyWithModifiers('h',[COMMAND,SHIFT])
# send key sequence to select first file there
firefoxwindow.sendKeyWithModifiers('a',[COMMAND])
# press the now active Open button
openbutton = firefoxwindow.buttons('Open')[0]
openbutton.Press()
It's theoretically possible, but really awkward. I'll give you a bunch of links--not ideal, I know, but you could write a book on this.
You'd need to start by enabling AppleScript control of the GUI. Then you'll want to read up on how to control the GUI from within Applescript. However, you wanted to use Python and not AppleScript, so then you'll need to install PyObjC, which is a Python to Cocoa bridge. You'd need to use the Scripting Bridge framework and figure out (from the extremely thin documentation) how to translate the AppleScript docs to Python.

Displaying icon in mac statusbar with python

I have a script that just returns true/false depending on some conditions, and I need to display this status in the status bar/some topmost window, the script is written in python.
I tried to find a way to display a status bar icon with python but seems all existing wrappers are outdated. I feel that it is not very good solution to create a native app just for displaying an icon and control it with my script.
I thought about using GeekTool for mac, but it can display stuff only on the desktop. Since the desktop is hidden with some windows all the time, that's not very good solution.
Any ideas?
Have found out that
import objc, from Foundation import *
from AppKit import *
from PyObjCTools import AppHelper
solves my problem

Categories

Resources