I record a lot of videos, so I have a MacBook Pro with two monitors connected. One of those monitors has a resolution set to 1920x1080. I record all my videos from that specific monitor. Right now, I run Google Chrome and Visual Studio Code. Then, I resize the windows for the specific conditions of my recording (sometimes Chrome uses more space, sometimes VSC does), so this is not a matter of simply doing a side-by-side setup where each app takes up a certain percentage.
That manual process is tedious and I usually want them to be a very specific size based on what I am recording. That is why I want to use AppleScript to simply resize the currently running applications based on various recording scenarios.
To create a test case, I wrote the following code. While it does the trick of perfectly resizing the app, it moves Chrome from the monitor I am recording on to my MacBook Pro's connected display.
Here is what I wrote so far:
set theApp to "Google Chrome"
set xLocation to 0
set yLocation to 0
set appWidth to 750
set appHeight to 1080
tell application "Google Chrome"
set bounds of front window to {0, 0, appWidth, appHeight}
end tell
Unfortunately, I am very new to AppleScript and have not been able to figure out how to prevent the script from moving the app (Google Chrome in this case) from the current monitor to the MacBook Pro monitor. I suspect it is that front window code, but I am struggling to learn how that works as I cannot find the documentation.
How can I use AppleScript to resize an application that is currently running without moving the application's window to another monitor?
I suppose if the answer is to open a new copy of the application, that would work too, so long as I can open or move it to the proper monitor. Thanks!
Update
Close, but not quite there...
I was provided this link in the comments. The code looks like this:
set theScreens to paragraphs of (do shell script "system_profiler SPDisplaysDataType -detailLevel |grep \"Resolution:\" | awk -F\"Resolution: \" '{print $2}'")
set theMonitor to ""
log theScreens
set the counter to count of theScreens --- set to 1 if you want to test it on monitor 1
if (counter) > 1 then
-- we will do things for monitor 2
set thisDisplayWidthHeightMonitor_2 to {(word 1 of item 1 of theScreens) + 2, 0, ((word 1 of item 1 of theScreens) + (word 1 of item 2 of theScreens)), word 3 of item 2 of theScreens}
set theMonitor to thisDisplayWidthHeightMonitor_2
else
-- we will do things for monitor 1
set thisDisplayWidthHeightMonitor_1 to {0, 0, (word 1 of item 1 of theScreens), (word 3 of item 1 of theScreens)}
set theMonitor to thisDisplayWidthHeightMonitor_1
end if
tell application "Safari"
activate
make new document with properties {URL:"http://netflix.com"}
set bounds of window 1 to theMonitor
log theMonitor
end tell
tell application "System Events"
tell application process "Safari"
set value of attribute "AXFullScreen" of window 1 to true
end tell
end tell
If I log the variable theScreens, I get the following result:
(*3072 x 1920 Retina, 3840 x 2160 (2160p/4K UHD 1 - Ultra High Definition), 4608 x 2592*)
That code does not show me the correct x position I need for my window placement. It just shows the monitors I am using and their UHD resolution.
When the code opens Safari (in this case), it sets the bounds with the variable theMonitor, and it does indeed open in the monitor I want it to. The output is:
3074, 0, 6912, 2160
Since the code does display the application in the monitor I want, I assume that 3074 is the correct x position for my need, so here is my updated code:
tell application "Google Chrome"
set bounds of front window to {3074, 0, 750, 1080}
end tell
Unfortunately, Google Chrome completely disappears off the screen and is nowhere to be found on any monitors or desktops. I have to quit Chrome and restart so I can use it again (or do the change the change-the-screen-resolution trick).
I am still left with the following question: How do I open the app in the correct monitor I desire and in the x & y location I desire?
Related
I am looking for a script that will place the cursor in the text field in the Messages App. I have looked for a keyboard shortcut to do this but cannot find one. Can anyone provide a script, or a similar one I can modify.
NB I am not a programmer or very familiar with AppleScript, but have been able to modify scripts that are close to my needs.
I need this as I am trying to make the messages app controllable using the built in dictation feature in Mac OS. I need a script I can assign to a voice command to place the cursor in the text field so that I can then dictate a message.
Many thanks.
If you are using dictation commands, in any application all you need to do is say the command “Show Numbers” and you will see this:
Then you would just say the command “Twenty” which will place your cursor right where you want it… in this case it would be the text field
Also speaking the command “Show Comands” Will open up this window listing tons of dictation commands.
The following was tested and works under OS X 10.8.5 and Messages 7.0.1 and may need to be adjusted for other versions of OS X/macOS/Messages:
tell application "Messages"
activate
tell application "System Events"
set focused of text area 1 of scroll area 4 of splitter group 1 of window 1 of application process "Messages" to true
end tell
end tell
Note: This is coded with the assumption that Messages is already open with an open window. Additional coding will be necessary, in the form of try and or delay and or on error statements as needed and appropriate otherwise.
Here's an example of how I'd code it otherwise, which handles whether or not Messages is open, has its window showing, etc.
on setFocusToTextArea()
tell application "System Events"
if (count of windows of application process "Messages") is equal to 0 then
click UI element "Messages" of list 1 of application process "Dock"
delay 0.25
end if
try
set focused of text area 1 of scroll area 4 of splitter group 1 of window 1 of application process "Messages" to true
end try
end tell
end setFocusToTextArea
tell application "Messages"
if running then
my setFocusToTextArea()
else
activate
delay 2
my setFocusToTextArea()
end if
activate
end tell
Note: If Messages is closed when this script is run, the delay 2 command gives time for Messages to open before the other code runs. The value of the delay command can be adjusted as appropriate for the speed of your system.
I've been working on an application in Automator that changes the desktop background to the album art of the current song playing in iTunes.
You can download my first version here.
The most annoying issue I have found is that when there is a full screen app open on the same display being updated, whenever the song changes the background flickers between the current song and the previous.
This is my current code (Updated from version 1.0 above):
You may need to scroll within the code to see all of it.
tell application "System Events"
set fileName to (((path to desktop) as text) & ".iTunesArt2-1.jpg")
set oldFile to open for access file fileName with write permission
write 0 to oldFile
close access oldFile
delete file fileName
if process "iTunes" exists then
tell application "iTunes"
if (player state is not stopped) then
-- get the raw bytes of the artwork into a var
tell application "iTunes" to tell artwork 1 of current track
set srcBytes to raw data
end tell
-- write to file
set outFile to open for access file fileName with write permission
-- truncate the file
set eof outFile to 0
-- write the image bytes to the file
write srcBytes to outFile
close access outFile
end if
end tell
tell desktop 2
set picture to fileName
end tell
end if
set fileName to (((path to desktop) as text) & ".iTunesArt2-2.jpg")
set oldFile to open for access file fileName with write permission
write 0 to oldFile
close access oldFile
delete file fileName
if process "iTunes" exists then
tell application "iTunes"
if (player state is not stopped) then
-- get the raw bytes of the artwork into a var
tell application "iTunes" to tell artwork 1 of current track
set srcBytes to raw data
end tell
-- write to file
set outFile to open for access file fileName with write permission
-- truncate the file
set eof outFile to 0
-- write the image bytes to the file
write srcBytes to outFile
close access outFile
end if
end tell
tell desktop 2
set picture to fileName
end tell
end if
end tell
I got the actual code that saves the artwork to a file from here.
The desktop will not update unless you give it a new file name to update, therefore I have duplicated the process with "iTunesArt2-1" and "iTunesArt2-1".
The first 2 in '2-1' or '2-2' simply means the second desktop, as I have two different applications to change each desktop, and use my 2nd desktop for testing.
The entire application is set to loop for 1000 years, using three separate Loop functions in Automator (720 minutes, 730 times & 1000 times).
When first trying to debug this issue, the process was duplicated into four separate scripts, one for saving the image, then setting as background, and two more scripts to repeat the process with a new file name.
Here's an example of my debugging:
I remove the opening period from ".iTunesArt##.jpg" so that I can see the files on my desktop.
I play a Coldplay song and run the application in Automator to set the background.
"iTunesArt2-1.jpg" and "iTunesArt2-2.jpg" are shown on my desktop with the correct album art.
I stop the application, and play a Paramore song.
I run the first script of the application (Saves the album art).
"iTunesArt2-1.jpg" is updated to the Paramore artwork.
I run the second script of the application (Sets background image).
Note, this script should be setting the background to the Paramore image.
The background remains set to the Coldplay image.
At first I think this is only because the background image was already set to "iTunesArt2-1.jpg", and therefore the system will not try to update it again, not knowing the data in the file has been changed.
So I run the next script which should force the background to update:
I run the third script in the application.
"iTunesArt2-2.jpg" is updated to the Paramore artwork.
I run the forth script in the application.
The desktop background is updated to the Paramore artwork.
So, we can confirm that scripts 3 & 4 worked correctly.
According to the code, when the application loops back to scripts 1 & 2, the desktop background should remain as the Paramore artwork.
BUT...
I run the first script in the application.
"iTunesArt2-1.jpg" remains the Paramore artwork (as it should).
I run the second script in the application.
This script should update the desktop background from ""iTunesArt2-2.jpg" (Paramore) to "iTunesArt2-1.jpg" (Paramore).
The desktop background changes to the Coldplay artwork.
Now that makes zero sense at all.
This will happen every time I loop through the scripts.
Script 4 will change the desktop to Paramore and script 2 will change it back to Coldplay.
Remember this issue only happens when there is a full screen app open on the same display being updated. ie. A full screen app open on my primary display doesn't matter.
I have found sometimes that sliding over to the full screen app and 'activating' it will stop the flickering, and the background will be set correctly.
There surely is nothing 'wrong' with my code is there? If not, I need a way to get around this issue.
Specifically, is there a way of 'activating' every full screen app in the background without moving to those spaces?
I would love anyone who wants it to have this program, but it needs to be able to run under all circumstances.
Any help would be greatly appreciated.
Found a work around which creates a random file name each time, meaning the desktop can't get confused as to which image it is supposed to display.
screenNum refers to which screen the desktop is being set to.
set randID to screenNum
set randLoop to 0
repeat while randLoop is not 9
set randNum to (random number from 0 to 9) as text
set randID to randID & randNum
set randLoop to randLoop + 1
end repeat
Then included randID in the file name upon its creation.
Have not noticed any flickering using this method.
Note: This solves my problem, but does not answer my initial question of how one can activate a full screen app in the background.
I am trying to get the foreground application from my second monitor (In Mavericks, second desktop). Here's my code that only gets the foreground application:
tell application "System Events"
set frontApp to name of first application process whose frontmost is true
end tell
How can I change it so it gets the application from a specific desktop / screen?
I don't think you can do as you want. If you look at the properties of frontApp there is no property that would indicate which screen it is on. However, what you can do is check the location of the application's windows. If you get the properties of a window of a process then you will see that it has a "position" property. You could check those coordinates to determine which screen it is on.
For example, I have 2 screens. My laptop is setup to be the main screen. I know the screen resolution of the main screen is 1680x1050. Therefore, if I check a window and it has a position outside of those coordinates then I know it must be on the second monitor. Here's how I could do that.
NOTE: I can tell which applications have windows on the second monitor, but not which application on the second monitor is frontmost... like you asked. You'll have to figure something else out for that. I'm showing you this as an idea that maybe you can make workable for your situation.
Here I am only getting the first application with a window on the second monitor. This should show you the idea and you can adjust the code to do as you need.
set mainScreenResX to 1680
set mainScreenResY to 1050
tell application "System Events"
set firstFoundAppOnSecondScreen to missing value
set visibleApps to application processes whose visible is true
repeat with visibleApp in visibleApps
try
tell visibleApp
set {x, y} to position of window 1
if x > mainScreenResX or x < 0 or y > mainScreenResY or y < 0 then
set firstFoundAppOnSecondScreen to name
exit repeat
end if
end tell
end try
end repeat
return firstFoundAppOnSecondScreen
end tell
How can I set focus to a specific window of a given application using applescript?
I have several iTerm2 windows running on different displays. I want to set focus to a specified window using applescript.
I need two things, one script that collects the window ID's and prints them to stdout. I've got this:
tell application "iTerm"
set wins to id of every window
end tell
which prints 6 integers: 3034, 2528, -1, -1, -1, -1
Bonus Question: What are the four -1's ?
Then I try:
tell application "System Events"
activate window 3034
end tell
Upon which the only thing happening is that I lose focus of my current terminal (in which I am typing these commands), not matter whether I specify 3034 or 2528 as the ID.
You almost have it. You can filter out the "-1" window IDs as by only looking at visible windows:
tell application "iTerm 2"
set wins to id of every window whose visible is true
end tell
I figured this out by looking at the results of:
tell application "iTerm 2" to properties of every window
I noticed that the "-1" windows have the property visible:false
Then you can tell the window ID directly to the iTerm application instead of system events:
tell application "iTerm 2"
activate window 13195
end tell
I use my Mac Mini to play movies and music on while working on my MBP. I like to keep screen sharing open but reduced in size in the upper right corner of my screen so that I can effectively have a "PIP". When I want to tag a song that is playing or change the movie, I use a key command to make the window full size, then another key command to shrink it back and position it in the upper right corner.
Since I updated to Lion, I've been getting the following error:
error "Screen Sharing got an error: Can’t set window 1 to {1191, 22,
1441, 185}." number -10006 from window 1
The code is below. Does anyone know what I'm doing wrong?
tell application "Screen Sharing"
activate
set the bounds of the first window to {1191, 22, 1441, 185}
end tell
I have also tried changing the code to use the wording "set the bounds of window 1..." but get the same error.
Any help would be much appreciated.
--Adam
If you look at the applescript dictionary for the application, it doesn't know those commands (e.g.. window or bounds). It only knows the GetURL command so it certainly won't work.
However there is another option. System Events knows about windows and it knows the size and position commands. So you can use that instead...
tell application "System Events"
set ssProcess to first process whose name is "Screen Sharing"
tell ssProcess
tell first window
set position to {0, 20}
set size to {605, 400}
end tell
end tell
end tell
tell application "Screen Sharing" to activate