Positioning windows with applescript on dual monitors - macos

I have 2 air applications that I wrote. They auto fullscreen after 10 seconds. Before then, they need to be sent to their proper displays. "app_1" needs to run on display 1, "app_2" needs to run on display 2.
Essentially, I have this code:
do shell script "cd /Applications/app_1.app/Contents/MacOS/ ; open app_1;"
which works for me flawlessly. Both apps are launched that way, and there is some code for ensuring that the apps weren't already open, and closing them if they were.
I tried to add in a script to position the app after it is launched:
do shell script "cd /Applications/app_1.app/Contents/MacOS/ ; open app_1;"
tell first window of application "app_1" to set bounds to {0,0,1920,1080}
This gives me an error:
app_1 got an error: Can't set bounds of window 1 to {0,0,1920,1080}
I tried adding a delay of a couple seconds before the set bounds, in case the application hadn't yet launched when the set bounds fired off, however this didn't change anything.
I also tried setting the bounds to something like {100,100,200,200} just to see if I had the screen coordinates wrong or something, but still the exact same error, only with the {100,100,200,200} instead of the original 1920x1080 coordinates.
Anyone have any insight on this? I've been trying to find the solution on google for a couple of hours now.

It sounds like your app isn't exposing the standard "window" class. I don't know if AIR apps are supposed to automatically take care of this and it's not working—if so, you'll want to debug that.
But another alternative is to use UI Scripting to control its windows externally. Instead of this:
tell first window of application "app_1" to set bounds to {0,0,1920,1080}
Do this:
tell application "System Events"
set position of first window of application process "app_1" to {0, 0}
set size of first window of application process "app_1" to {1920,1080}
end tell
However, this will only work if you've gone to the Universal Access pane of System Preferences and checked "Enable access for assistive devices" (or done the same via API, "sudo touch /var/db/.AccessibilityAPIEnabled", etc.).

Related

MacOS: Determine which monitor any window application is on?

I'm currently attempting to have my system pipe audio to a specific output depending on which monitor that application is running on. For instance, if a web browser is playing videos on monitor A, sound comes out of output 1. If it is on monitor B, it comes out of output 2. Is there any way to poll which monitor any/all applications are located/active on macOS?
The question hasn't given many details, but in principle you can recover the position of the window using code like the:
tell application "System Events"
tell process "App Name"
set windowPos to position of first window
end tell
end tell
... and then compare that to the frame of each desktop to discover which display the window is in. If you need to determine the frame of each desktop programmatically (instead of hand-coding them in), that will take some extra work: either digging the values out of a system plist file or using AppleScriptObjC to get the frame dimensions from NSScreen. Let me know if you need that, and I'll update when I get a chance.

Allow JavaScript from Apple Events in Safari through Terminal Mac

I'm writing a program that executes do javascript in Safari. The only problem is that I'm trying to make the app give its self permission to do it. I'm trying to locate the file that handles the Safari developer preferences so that I can do this. Does anyone have any idea where this might be or how to change these settings?
It's in Safari's preferences plist at ~/Library/Preferences/com.apple.Safari.plist. The key you want is AllowJavaScriptFromAppleEvents. You can set it using defaults:
#to turn it on
defaults write -app Safari AllowJavaScriptFromAppleEvents 1
#to turn it off
defaults write -app Safari AllowJavaScriptFromAppleEvents 0
The virtual keyboard thing did not work for me. As StarPlayr at apple's develepoer forum has found out the problem is in something else.
For me problem occurred when i tried to do that on remote mac.
For some people plugging in a keyboard and mouse to the Server allowed to turn on JavaScript Apple Events in Safari and set the password.
However, for me that wasn't an option, so the next best thing is use an accessbility scripting feature and have the machine think a user is doing the clicks, allowing you to set the password:
-- The delays can be shorter, coordinates may vary
-- Best way to get the coordinates is with Apple screen capture (command-shift-3) from upper right to lower left (the coordinates will be shown)
-- if one spends the time, the click events can be converted to Accessibility AppleScript objects by capturing them as variables, or checking the events and using the events instead of the click coordinates
tell application "System Events"
tell application "Safari"
activate
end tell
delay 1
-- click develop menu (make sure its on first)
click at {430, 12}
delay 1
-- click Allow Javascript menu from Apple Events
click at {615, 615}
delay 1
-- Click the Allow Button
click at {1010, 386}
end tell

Screen Sharing with Applescript and Automator

Desired Results:
1. Open Screen Sharing.app
2. Input desired IP address and connect (changes depending on environment)
3. Auto Mute Microphone
4. Wait for session to connect
5. Auto switch to Observe Mode
6. Session is complete and Screen Sharing.app is closed
7. Auto UnMute Microphone
What's been done and needs:
1. I have successfully done steps 1, 2, 3, 6, and 7.
2. I am stuck trying to find a way to trigger the Observe Mode without using a timer. If the desired connection isn't complete within the designated time or the window is not selected, it will not work and an error will occur.
3. I am using a combination of Automator and Applescript. Most of the items are setup by Applescript.
My question:
How can I tell Automator or Applescript to wait for Screen Sharing to finish connecting before proceeding with the remaining tasks?
Except GetUrl instruction, screen sharing app is not scriptable, then you cannot ask it if the vnc connection is on or not. Screen sharing app has an internal timeout which triggers an error window ("can't open...") after sometime.
So you can't know when the screen sharing will have open the windows or just the error dialog. The work around I used is to check, before opening vnc url, that your IP address answers to ping requests. But you may have some servers which don't answer !
The second part is easier because the switch to observe mode can be done via keystroke (screen sharing menu) with script bellow :
tell application "Screen Sharing" to activate
tell application "System Events"
tell process "Screen Sharing"
keystroke "x" using {option down, command down}
end tell
end tell
Of course, this is only valid once screen sharing has open the vnc window. And you must allow, in system preferences, the GUI scripting via your application.

OSX: Lock the screen programmatically

I'm looking for a way to lock the user screen programmatically without putting the Mac asleep.
Right now, i'm able to trigger the lock screen with the kAESleep event but it's more a hack and it put the computer asleep.
Is it possible ?
Thanks
Configure the screensaver to require a password immediately after it starts, then start the screensaver programmatically. I have it programmed to a keyboard shortcut to help my Windows folks transition to using real computers ;).
The following AppleScript will do it for you. Note that because of security limitations of OSX, AppleScript pauses for five seconds before it executes an UI function, so it takes a small while to function. I'm using Quicksilver to bind it to a hotkey.
(As a bonus, this script will also pause a couple of your music players. Feel free to remove those lines.)
#
# Tell our noisy programs to shut up
#
tell application "Spotify"
pause
end tell
tell application "iTunes"
pause
end tell
#
# Lock up the screen without going to sleep. Needs that Keychain Access
# is set up properly.
#
tell application "System Events" to tell process "SystemUIServer" to click (first menu item of menu 1 of ((click (first menu bar item whose description is "Keychain menu extra")) of menu bar 1) whose title is "Lock Screen")
You will need to set up Keychain Access so that it has the lock icon on screen though.
I was successfully able to lock the screen on macOS in python with the following
import ctypes, ctypes.util
login = ctypes.CDLL( '/System/Library/PrivateFrameworks/login.framework/login' )
login.SACLockScreenImmediate()
I discovered this by scarce information on the Internet and trial-and-error. As far as I know, Apple doesn't document the SACLockScreenImmediate() function at all.
If anyone can find the official reference documentation for the "Login Framework" library, please drop it in the comments :)
Source
The is used in the BusKill app, which locks the screen when a magnetic breakaway connection in a USB Dead Man Switch is severed:
https://github.com/BusKill/buskill-app/tree/master/src/packages/buskill

How to minimize MOG using applescript

I am working on an AppleScript to toggle between minimize and maximize of specific windows. I have it working pretty well. But I am running into a specific issue with one application the MOG app for Mac does not seem to have a variable for miniaturize, collapse, or minimize.
I know that I could use click to toggle the window, but I would prefer a solution that works with the API.
Here is the applescript just for MOG:
tell application "MOG"
set (miniaturized of windows whose miniaturizable is true) to true
end tell
I would really appreciate it if someone could point me in the right direction.
Not every application is going to allow something like miniaturization of windows via AppleScript, even when the application is scriptable. One way to find out the properties of an application's window:
tell application "MOG"
get properties of window 1
end tell
You can also open the MOG dictionary and find out what you're able to script. Pressing cmd-shift-o will open a window listing all applications' scripting dictionaries.

Resources