I'm trying to select OK with the popup for scaling the screen with Apple script.
Does anyone know what I can add to this script to allow me to click OK?
Apple Script:
tell application "System Preferences"
reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
end tell
tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
click radio button "Scaled" of radio group 1 of tab group 1
click radio button 1 of radio group 1 of group 1 of tab group 1
(* Trying to click the ok button here *)
delay 1
click ((pop up buttons of sheet 1 of window 1) whose description is "OK")
end tell
quit application "System Preferences"
Or also rather does anyone know a trusted application that can graphically print out the labels of the UI when I visit them on my screen so I will know what to use when I say: "tell UIName"?
Thanks.
Solution 1: Press Return
Since you're using System Events anyway, and the button in question is selected by default (indicated by being highlighted in blue), just make sure that the preference pane is in focus and use System Events to hit the return key:
tell application "System Events" to keystroke return
It's quick, simple, and saves the hassle of identifying UI elements within the hierarchy. The drawback is that the preference pane has tone in focus, and if it loses focus before it receives the keystroke, the rest of the script will fail.
Solution 2: The One You Asked For
Regarding identification of UI elements within the GUI objects hierarchy, you got the class of the button in question wrong as well as its description.
The "OK" button is referenced like so:
tell application "System Events" to tell process "System Preferences" ¬
to get button "OK" of sheet 1 of window "Built-in Retina Display"
(window 1 is also fine). You can use the whose filter to target it instead, which would be done like this (via System Events and the System Preferences process):
get buttons of sheet 1 of window 1 whose name is "OK"
but all this does is ask AppleScript to search for a button whose name we know, then annoyingly give the result back to us as a list (the list structure can be flattened by requesting the first button of sheet 1...).
However, we do know its name and that there's only one of it, so we can reference it by name directly.
As a side-bar, if you quickly run this command:
get the properties of button "OK" of sheet 1 of window "Built-in Retina Display"
you'll be able to see that its description is merely "button", which isn't what you had hoped. Now run this command:
get the actions of button "OK" of sheet 1 of window "Built-in Retina Display"
which reveals it has one action available, AXPress (this is equivalent to a mouse click).
Therefore, finally, the way to click the button in a more satisfactory way than hitting the return key looks like this:
tell application "System Events" to tell process "System Preferences" ¬
to tell button "OK" of sheet 1 of window "Built-in Retina Display" ¬
to perform action "AXPress"
For exploring the GUI objects on the screen, I occasionally use the Accessibility Inspector that comes with Apple's XCode. It's vaguely useful, although inconveniently annoying with some of the discrepancies between the names by which it references objects and the names by which AppleScript does (they're also really subtle discrepancies, but enough to stop your script from working and send you into a frenzy for weeks).
So, actually, I just explore it programmatically myself in Script Editor.
What I did to solve your issue was to bring up the pane and the dialog box in question, then systematically tell the System Preferences process to get UI elements; then get buttons of UI elements; then get buttons of UI elements of UI elements, and stop when I saw a pair of buttons returned called "OK" and "Cancel". It can be pain-staking, but it'll get you the correct reference.
There are other ways too, but I would be moving beyond the scope of this question.
Related
Can you rewrite this applescript for Monterey?
tell application "System Preferences" to reveal anchor "Seeing_ColorFilters" of pane "Accessibility"
tell application "System Events"
tell process "System Preferences"'s first window's first group's first tab group
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, uncomment the following line to allow time for the menu to open
-- delay 0.1
tell its menu
click menu item 1
end tell
end tell
end tell
end tell
tell application "System Preferences" to quit
This code is a script that makes the display grayscale. I used to use this code in BigSur. However, after updating the version to Monterey, it stopped working. My Monterley version is 12.6.2.
Thanks,
The problem appears to be a timing issue. The menu that your script uses to select the greyscale option is no longer immediately available under Monterey 12.6.2. A short delay is required.
I took this script and enabled it one line at a time. With the System Preferences window already open and the color filters pane revealed, it worked all the way to the end.
So, I then ran the full script with System Preferences closed. It failed at the line:
click checkbox "Enable Color Filters"
with the error:
Script Error
System Events got an error: Can’t get group 1 of window 1 of process "System Preferences". Invalid index.
That error sounds like the window isn’t yet available. So I tried adding a delay in front of clicking the checkbox:
delay 0.1
click checkbox "Enable Color Filters"
The script then began to work as I assume you wished it to: the checkbox is checked, the first item on the menu (Greyscale) is selected, and the screen goes greyscale.
However, a hard-coded delay seems likely to fail if the system takes variable amounts of time to make the window available. So, rather than hardcode the delay, I added a loop to check for the existance of the desired checkbox:
repeat while not (exists checkbox "Enable Color Filters")
delay 0.1
end repeat
click checkbox "Enable Color Filters"
This version should work in past and future operating systems even if the timing changes, as long as the terminology remains the same.
The same technique should also work for your commented-out delay that waits for the menu to become available:
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
Currently, the script toggles between greyscale and no filtering. That is, if the checkbox is already checked, this script will uncheck it. If your purpose is to ensure that the screen is always in greyscale, as your question implies, you may wish to verify the value of the checkbox first:
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
end if
Checkboxes have a value of 0 or 1, depending on whether they’re currently checked (1) or unchecked (0).
If, on the other hand, your goal is for the script to toggle between the two states, there’s no reason to play around with the menu if you’re toggling color filters off:
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
else
click checkbox "Enable Color Filters"
end if
Assuming the purpose is to guarantee the screen is in greyscale, the full script might end up looking like this:
tell application "System Preferences" to reveal anchor "Seeing_ColorFilters" of pane "Accessibility"
tell application "System Events"
tell process "System Preferences"'s first window's first group's first tab group
-- if necessary, allow time for the checkbox to become available
repeat while not (exists checkbox "Enable Color Filters")
delay 0.1
end repeat
--ensure that greyscale filters are enabled
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
end if
end tell
end tell
tell application "System Preferences" to quit
I'm a uni student taking online courses, I take portion screenshots by pressing Command+Control+Shift+4 every time to take notes, then I paste it to Notion. But it's not efficient to select the same area every time, then I found that QuickTime Player will keep the same area for capturing a portion screenshot, so I decided to use Apple Script to complete the operation.
The code I wrote could switch to the application QuickTime Player and then proceed to "New Screen Recording" in the menu by pressing Command+Control+N, but the problem is that sometimes pressing twice space will call out "Capture Selected Window" instead of "Capture Selected Portion". Meanwhile, the location where saving the screenshots will also be changed too though I already ticked "Remember Last Selection", maybe resetting the location to be saved every time is essential.
on run {input, parameters}
activate application "QuickTime Player"
tell application "System Events"
key code 45 using {command down, control down}
delay 0.1
# Switch to "Capture Select Portion" by pressing SPACE
repeat 2 times
key code 49
delay 0.1
end repeat
# Press ENTER to capture a screenshot
key code 35
delay 0.1
end tell
return input
end run
I spent a few hours finding the existed articles but perhaps not that fulfill my needs.
do shell script "screencapture -ci" is as same as pressing Command+Control+Shift+4, and I have to select the portion manually.
do shell script "screencapture -x -R20,20,640,380 ~/Desktop/test.png" needs a precise coordinate. But the coordinate is variable since the window is not fixed, and it needs to be found by using external software, maybe it's a little bit not efficient. If there is no solution for that, I will use it since it's much more convenient than selecting the portion every time.
Sorry about pasting others' code here and saying why they r not suitable for me, I just wanted to make it clear... Thanks for reading here, have a nice day no matter if u r willing to help me ^ ^
The part about pasting screenshots to Notion works, so I didn't paste it here.
I tried writing something, it works but still has some bugs.
For example, the coordinate of the menu "Options" should be initialized depending on the precise location of the bar since I didn't succeed in finding the element by using entire contents.
You can't move your mouse during the use, or it might cause an error:
System Events got an error: Can’t get menu \"Options\" of button \"Options\" of window \"Window\" of application process \"screencaptureui\"." number -1728 from menu "Options" of button "Options" of window "Window" of application process "screencaptureui
When selecting the path where screenshots will be saved, it might take a few seconds to let the program find the menu item Clipboard.
tell application "System Events"
tell process "QuickTime Player"
# Switch to QuickTime Player (already opened expected, no launching time reserved)
activate
# Open "New Screen Recording" from the menu
click menu item "New Screen Recording" of menu "File" of menu bar item "File" of menu bar 1 of application process "QuickTime Player" of application "System Events"
delay 1
end tell
# Capture Selected Portion
tell application process "screencaptureui"
click checkbox "Capture Selected Portion" of window "Window" of application process "screencaptureui" of application "System Events"
# Select Options from the menu (idk why if I replace it with click menu, the clipboard won't be found, needs to be fixed)
click at {817, 824}
delay 0.1
# Save to the Clipboard
click menu item "Clipboard" of menu "Options" of button "Options" of window "Window" of application process "screencaptureui" of application "System Events"
delay 1
end tell
# Enter to capture the screenshot
key code 36
delay 0.1
# Switch to Notion (already opened expected, no launching time reserved)
tell application "Notion"
activate
delay 0.1
end tell
# Paste the screenshot to Notion
key code 9 using {command down}
end tell
Hope this helps someone, if u hv any idea plz feel free to modify it since it still has bugs.
Actually I have 3 questions about the same problem: controlling a window with applescript.
What should I do if I would press on button "Close Window" of application "Google Chrome"?
Is it possible to check if the window changes? For example, to see if appear a pop-up or something like that...
What about clicking on a specific place into a window? I mean, I know I can use
tell application "System Events"
click at {x,y}
end tell
but this command use the entire screen as reference system, and I want it works only on a specific window. For example, if at "{x,y}" i put "{1,1}", applescript will click on the first item on the menu bar. Is there a way I can say to "System Events" to click at "{1,1}", but on the window "Google Chrome"?
Here are three examples of how to close the front window of Google Chrome using AppleScript:
Note: The following assumes Google Chrome is running with at least one window open when you test each example AppleScript code in Script Editor.
Example one is the most straight forward way:
tell application "Google Chrome" to close front window
Example two directly clicks the close button:
tell application "System Events" to tell ¬
application process "Google Chrome" to ¬
click button 1 of front window
Example three calculates the center of the close button and clicks there:
activate application "Google Chrome"
delay 0.5
tell application "System Events" to tell ¬
application process "Google Chrome" to tell ¬
front window
set posB1 to (position of button 1)
set szB1 to (size of button 1)
set x to (item 1 of posB1) + (item 1 of szB1) / 2 as integer
set y to (item 2 of posB1) + (item 2 of szB1) / 2 as integer
end tell
tell application "System Events" to click at {x, y}
Note that in the first two examples, the front window of Google Chrome doesn't even need to be the frontmost window on the Desktop; however, with the third example it does, otherwise the click at {x, y} will not go to the intended target.
That said, example three really shouldn't be used when there it a straight forward way, as in example one, to get the job done. Example three was just a proof of concept to get the coordinates to click at. This method may be useful in some fringe cases, especially in an app that doesn't directly support AppleScript.
Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors.
In applescript GUI scripting you can simply refer to an element by name or index and tell it to click or to perform an action. For instance to click the close button on the first open window in Chrome you could use:
tell application "System Events"
tell process "Google Chrome"
tell window 1
tell button 1
click
end tell
end tell
end tell
end tell
You don't actually need to know its physical position to click one it; you just need to know that the first button in the window is the close button.
System Events always returns the position of any element in screen pixels, so if you want the position of an element in terms of its window, get the position of the element, get the position of the window, and do some addition or subtraction (e.g., if you want to click at {5,5} in a window whose position is {100, 125}, click at {105, 130})
AppleScript isn't really designed to monitor GUI changes, though if you want to be tricky and you know what change you're looking for you can do something like this:
tell application "System Events"
tell process "..."
tell window 1's pop up button 3
repeat until (exists menu 1)
delay 0.2
end repeat
-- menu 1 now exists, so the pop up button is open
end tell
end tell
end tell
...but note that this will hang the script until the menu is opened. A more elegant way to handle that is to write a script application with an idle handler, like so:
on run
-- whatever initialization is needed
end run
on idle
tell application "System Events"
try
tell process "..."
tell window 1's pop up button 3
if exists menu 1 then
-- menu 1 now exists
-- the pop up button is open
-- do what must be done
end if
end tell
end tell
on error errstr
display alert "Something went wrong" message "The script sent this error: " & errstr
end try
end tell
return 0.2
end idle
You can leave that running in the background watching for specific changes in the GUI (the 'try' statement is in case the app you're watching quits, the window closes, or something unexpected happens to the GUI).
If you haven't already, open the System Events scripting definition in Script Editor and look at the Processes Suite. That will show you all the things you can do with GUI scripting.
I'm newbie to Appplescript. I need to automate certain actions on my computer related with my Bluetooth keyboards.
I want to be able to click on the remove or connect button of a keyboard in the following dialog window of the System Preferences Panel.
Dialog window
My code until this moment is as follows:
try
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.keyboard"
end tell
tell application "System Events"
tell process "System Preferences"
click button "Set Up Bluetooth Keyboard…" of window "Keyboard"
end tell
end tell
tell application "System Events"
tell group 1 of window 1 of application process "System Preferences"
click button "remove" of "Home Keyboard"
end tell
end tell
end try
My problem is related with the remove button since is unidentified cell of an unidentified table. With unidentified, I mean without description. Maybe there is an easy solution, but I'm not able to find it. Furthermore, It could happen that more than one keyboard exists, so I need to identify the cell from the Keyboard name.
Do you know any hint related with this issue?
Thanks in advance
Here is a sample script I used to reconnect a specific mouse via Bluetooth :
tell application "System Events"
tell application "System Preferences"
activate
reveal anchor "MouseTab" of pane id "com.apple.preference.mouse"
end tell
tell application process "System Preferences"
click button "Configuration of Bluetooth mouse…" of window 1 -- see note 1
delay 1
select (first row of table 1 of scroll area 1 of sheet 1 of front window whose value of item 1 of static text of UI element 1 contains "Mouse") -- see note 1
get value of item 1 of static text of UI element 1 of row 2 of table 1 of scroll area 1 of sheet 1 of front window
click button "Done" of sheet 1 of front window -- see note 1
end tell
tell application "System Preferences" to quit
end tell
Note 1 : Be careful about the 3 lines with comment 'see note 1' : the value of the string may be different for your local language. Please adjust these 3 values.
I think for keyboard, concept should be very similar. Because it is using GUI scripting, if Apple changes the layout of Bluetooth screen preferences, it must be adjusted. This script works from Yosemite to ElCaptain.I can't test it for next systems.
I want to automate clicking a specific pop down menu's item.
For Example, I want to change the Value of "Message receive Sound" to something else. How can I do this with AppleScript? And how can I do this with other pop down menus in AppleScript?
(To open the iMessage Settings menu, shown in the image, type CMD COMMA, once you open iMessage)
Note: I have successfully done this Automator, I just want to do it in applescript.
It's called GUI scripting. You have to identify the reference to the UI element(s).
GUI scripting strongly depends on the system version. If an update changes the UI structure the script will brake.
This selects the sound "Popcorn" in the sound popup menu. It's for El Capitan. In systems < 10.11 the UI elements may be different and the process name might be "iChat"
tell application "System Events"
tell process "Messages"
set frontmost to true
if not (exists (1st window whose value of attribute "AXIdentifier" is "MessagesPreferencesWindow")) then
keystroke "," using command down
repeat until exists (1st window whose value of attribute "AXIdentifier" is "MessagesPreferencesWindow")
delay 0.1
end repeat
end if
tell (1st window whose value of attribute "AXIdentifier" is "MessagesPreferencesWindow")
tell pop up button 4 of group 1
click
delay 0.2
click menu item "Popcorn" of menu 1
end tell
end tell
end tell
end tell