Making a another applications's window frontmost and focused - macos

I've been trying to get any given window from another Application to become front most and focused.
Here are the two methods I have tried:
AppleScript
tell application "Safari"
set index of window "Downloads" to 1
activate
end tell
Why it doesn't work: While it seems to change the z-Order, it doesn't change the focus! The previous frontmost window, even if obfuscated, retains focus.
CoreGraphicServices
CGSWindowOrder(cid, wid, kCGSOrderAbove, nil)
Why it doesn't work: Without being the Universal Owner, you can't change the order of a window owned by another process. In this case, making myself the Universal Owner is not an option -- I don't want to depose the Dock.
Recap
I need to make a window frontmost and focused from one process to another. AppleScript fails to focus, and CGS isn't an option since I don't own the window.
Any solutions/ideas?

Try using the Accessibility API to send an AXPress action to the AXWindow. Obviously, the user will need to have access for assistive devices turned on.

Related

How do I use AppleScript to close all applications that are hidden?

I have an applescript made to close all apps:
tell application "System Events" to set quitapps to name of every application process whose visible is true and name is not "Finder"
repeat with closeall in quitapps
quit application closeall
end repeat
It works just fine. It quits all open applications.
My problem is that I want to modify this script to close only the apps that are hidden. For some reason, Apple hides all Apple-made apps with no active windows, and eventually it starts eating up my RAM.
What I thought was that if I just change the line whose visible is true to whose visible is false I would get that result.
Not quite:
I don't even know what this window is supposed to be, so I just hit cancel.
Well, it pops up again. Turns out I have to hit cancel exactly four times before the script bombs out.
Is there any way to quit all hidden applications, while leaving open the visible ones?
(Bonus points if you can explain the pop-up above.)
If it makes a difference, I'm running the latest version of OSX.
Setting visible to false affects all processes – even processes / applications without a GUI. If a process is not an application (.app) the application chooser appears.
Add a check for background only which affects only applications with a GUI.
tell application "System Events" to set quitapps to name of every application process whose visible is true and background only is false and name is not "Finder" ...
If I understand correctly, you are talking about how when you press the red close button, it only closes the application's windows, but not the application itself, so it's just left there still open.
In which case, you can use this script I made, it seems it works flawlessly:
-- Get open apps
tell application "System Events" to set openApps to name of every application process whose background only is false and name is not "Finder"
-- Do this for every open app
repeat with openApp in openApps
tell application openApp
-- Tell application to quit if it doesn't have any open windows
if (count of windows) is less than or equal to 0 then quit
end tell
end repeat
OSX doesn't "hide" apps. They just aren't active, or don't have any documents open. Hidden apps is a very specific process usually done with Command-H. Apps don't hide themselves in this fashion.
Rather than trying to close apps with no windows, use the document count to determine whether to close an app.
tell application "SomeApp" if count of documents = 0 then quit
This is a quirky issue. For reasons unknown to me, you have to separate stuff in order to get it to work. This quits every non-background app that's not in the igApp list. I added 'without saving' to deal with document apps like TextEdit but obviously, it's optional. While this could likely be streamlined somewhat, it seems to work reliably.
tell application "System Events"
set igApp to {"Finder", "Script Editor", "firefox"}
set qList to {}
set fApp to name of every application process whose background only is false
repeat with xx in fApp
if xx is not in igApp then
copy contents of xx to end of qList
end if
end repeat
end tell
repeat with yy in qList
quit application yy without saving
end repeat
-- qlist
Note that if you want to quit some (or all) of your background applications you should probably reconsider. Those are doing things in the background and unless something goes awry, they generally don't abuse a computer's resources. Some may require force-quit to stop. If your computer is starved for RAM when it's idle, then either some app is broken/buggy or you need more RAM.
With that said, if you swap 'background process' to true, it should work on any of the background applications. As I said, I recommend against this but you could comment out the 'quit application' line and then uncomment 'qlist' (the last line), and then you'll get a list of those applications. You could look those apps up in Activity Monitor's Memory panel to see how modest these apps' demands are. On my mac, if you exclude obvious apps like 'Dock', combined they use < 200 MB of RAM.

How to open, close and close the dialogs of another application using cocoa or applescript?

I want to open another separate application, open the projects/documents of that application in a iterative way and then close the application. I also want to close all the modal and non modals dialogs which popped up during the opening of the document. I want to close all the dialogs including the crash dialog in case the application fails/ crashes.
What will be the best way using cocoa or applescript to achieve this and from where i can get more detailed information?
If the app has a scripting interface, of course the best way is to do that.
You generally don't want to iterate in AppleScript, but rather to operate on all of the results of a query.
For example, for almost any application that implements the "standard suite", you can just:
tell app "TextEdit" to close windows
This is much simpler (and faster, and more likely to be implemented correctly in the target app) than:
tell app "TextEdit"
repeat with theWindow in windows
close theWindow
end repeat
end tell
Of course this may pop up save/abandon changes dialogs, and it may skip over or include dialogs and inspectors, and so on, depending on the application's user model.
More importantly, it won't work if the app doesn't support scripting (and the standard suite).
Also, it won't help at all with closing a crash report—that window is owned by CrashReporter, not the original application (which is a good thing, because you can't talk to the original application anymore, now that it's crashed…).
The alternative is the UI Scripting features in System Events. This will only work if assistive access is enabled. It can also be a bit fiddly to figure out which windows are the ones you want to deal with, and which controls are the ones you want.
For example:
tell app "System Events"
click button 1 of windows of application process "TextEdit"
end tell
This works by finding every window (no matter what kind) owned by the TextEdit process, and simulating a click on the first button in that window (the red close button).
If you google "AppleScript UI Scripting" you should find lots of different guides. The first hit I found was http://www.makeuseof.com/tag/applescripts-ui-scripting-mac/ and it looks like a decent place to start.

Is there a way to get a permanent identifier for any given window

I'm trying to write a script that can control different windows from different programs (set position and size). I've got things just about working but I'm having problem accurately identifying windows. Right now I've got:
tell application "System Events"
tell application "Mail"
set windowName to name of window 1
end tell
end tell
This is a pretty simplified version of what I have working now. I'm grabbing the window information for many different applications and storing them as properties which are being called upon by another script later:
tell application "System Events"
tell application "Mail"
set position of window windowName to valueX
end tell
end tell
This works as long as the name of the window doesn't change. In many other applications I have no problems because window titles don't change (iCal, iChat, etc). In Mail the window title changes depending on how many e-mails are in your e-mail box. If an e-mail comes in between the first part of the script and the last then the script fails.
I can't really refer to the window by it's index number because those change as the order of the windows change (front to back). I thought maybe the window ID would work, but I need my script to work even if an application has been quit and restarted and the ID number changes if the application is relaunched. Am I SOL, or is there something I hadn't thought of?
Not SOL, but you'll have to do a little more work. There's only a few types of windows. You have the main browser window and you have email messages, whether it be a draft they are composing or an email message they're reading. Maybe you're concerned with the preferences window too. So you have to store the type of window. If it's a browser then you also will have to store the currently selected message. If it's an email window then you store the message id too. For browsers you just open a new browser window and restore the selection. For email messages you just open the messages. You'll have to check Mail's dictionary for other types of windows, but the idea will be the same.

How do I make a Safari window active using AppleScript (elegantly)?

While one can simulate command-shift-` using System Events to change windows in Safari, is there no better way to do this with AppleScript? I can change the index of Safari's windows, this changes their ordering on the screen but does not make them active. Suppose you have two Safari windows containing about:blank -- how could you bring the one in the back to the front and make it active?
Granted, command-shift-` works, so maybe there only needs to be one way to skin this cat.
I also noticed that changing the index does reorder the windows however the new window does not actually come to the front. By playing around I found you can fix that by playing with the "visible" property...
tell application "Safari"
set theWindows to windows
set win2 to item 2 of theWindows
tell win2
set visible to false
set visible to true
set index to 1
end tell
end tell

Applescript activate closed window

how can I activate an application and make it open the "standard" window as if I would have clicked on the dock icon with applescript?
E.g. I am in iTunes, close the window with command-w open another application and then I click on the iTunes dock icon and iTunes becomes the frontmost application and opens up it's "standard" iTunes window.
When I want to simulate that with applescript I type:
tell application iTunes to activate
What happens then is, that iTunes becomes the frontmost application, but the "standard" window (in that case the iTunes window) isn't being opened.
Does anyone know about a way to open the "standard" window with a general approach for any application?
Thanks b00tsy
after a long time I found out that what I expect to happen with
tell application "anyApplication" activate
actually happens with
tell application "anyApplication" reopen
There is no true, single way to show a "standard" window. It is up to the developer of each application to decide how a window is to be created and shown. For example, here is iTunes and Microsoft Word 2008...
tell application "iTunes"
activate
set theBrowser to browser window 1
set visible of theBrowser to true
end tell
tell application "Microsoft Word"
set newDocument to make new document
end tell
In iTunes, there are three "standard" windows—browser, EQ, and playlist—and browser and EQ always exist. But in Microsoft Word, however, we have to make a new document, which is as close to a "standard" as it gets. Most applications will work the same way Word does, but it isn't a guarantee and you will have to look at the Dictionary for a given application to see how it handles windows (although iTunes does have a window class to throw everyone off, but that's Applescript for ya...).
One more thing to note...in most cases, once a window is closed, the only way to reopen it is to open the file that populated the window you just created or simply create a new one. iTunes is rare in its implementation.

Resources