Start Screen Mirroring in Control Center with AppleScript - applescript

I want to start Screen Mirroring from my MacBook to my AppleTV with a keyboard shortcut. I used Automator's Recording function ("Watch Me Do") to record the three necessary clicks (open Control Center, click on Screen Mirroring, click on Apple TV). This is the resulting code:
-- Click the “Control Centre” menu bar item.
delay 0.608482
set timeoutSeconds to 2.0
set uiScript to "click menu bar item 2 of menu bar 1 of application process \"Control Centre\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” button.
delay 0.84342
set timeoutSeconds to 2.0
set uiScript to "click UI Element 6 of group 1 of window \"Control Centre\" of application process \"Control Centre\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” button.
delay 1.017773
set timeoutSeconds to 2.0
set uiScript to "click UI Element 2 of group 1 of window \"Control Centre\" of application process \"Control Centre\""
my doWithTimeout(uiScript, timeoutSeconds)
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
Now the problem is that when I execute that script, in the second step it's not Screen Mirroring that's being clicked but Focus, the element above it. So somehow the line set uiScript to "click UI Element 6 of group 1 of window \"Control Centre\" of application process \"Control Centre\"" doesn't work as expected. I tried to replace the UI Element 6 with other numbers. Most of them result in a click on Focus, others turn off Bluetooth or AirDrop ...
How can it be that a recorded action yields a different result when played back? Any ideas?
I'm on macOS Ventura btw.

Edit: Solution for Ventura 13.0.1
After some testing on a Ventura VM, I found that a lot of stuff changed between versions so what I posted initially as a potential solution won't work.
In your script change set uiScript to "click UI Element 6 of group 1 of window \"Control Centre\" of application process \"Control Centre\""
to
set uiScript to "perform action 1 of UI Element 6 of group 1 of window \"Control Centre\" of application process \"Control Centre\""
Worked for me on Ventura (I just had to change the spelling of "Centre" to "Center") but that is probably because we might have different system languages set.
This other thread describes some of the changes on Ventura for this problem.
I've had a lot of issues with applescript and interacting with the Screen Mirroring item in the Control Center dropdown. As well as, trying to use Automator's record function to do something similar. The Screen Mirroring item in the Control Center dropdown is technically a checkbox so a "click" action should work on it but it doesn't for some reason. While the same "click" action seems to work on other items in the same dropdown like "focus" or "bluetooth". The issue also seems to exist on Big Sur and Monterey. I found that you need to "perform action 2" (Monterey) and "perform action 1" (Big Sur) in order to "click" on it from Control Center dropdown.
I'm not on Ventura but this works for me on Monterey.
set uiScript to "perform action 2 of UI Element 6 of window \"Control Center\" of application process \"ControlCenter\""
Things change between system versions so I had to remove the "of group 1" part to get this line to run on my system. Also had to change the spelling of "Control Centre" (not sure why spelling is different) to "Control Center" and removed the space in "Control Center" on the "of application process" part.
With your current code this might work. I changed the "click" to "perform action 2" and instead of selecting UI Element by number I used the name. I left the spelling the same of "Control Centre" though.
set uiScript to "perform action 2 of UI Element \"Screen Mirroring\" of group 1 of window \"Control Centre\" of application process \"Control Centre\""
It's possible that "perform action 2" might not even work on Ventura, as it changed from "perform action 1" on Big Sur so it could have changed again.
Here is a snippet of a working solution I have for Big Sur and Monterey. I have added a section that might work for Ventura. From what I gather from your code it looks like Screen Mirroring is inside a "group 1" which was different from Monterey.
Edit: This won't work for ventura
tell application "System Events"
tell its application process "ControlCenter"
click menu bar item "Control Center" of menu bar 1
tell its window "Control Center"
-- Monterey
if exists checkbox "Screen Mirroring" then
tell its checkbox "Screen Mirroring"
perform action 2
delay 1
end tell
else
-- big sur
-- "action 1" instead of "action 2"
if exists (checkbox "Screen Mirroring" of group 1 of group 1) then
tell its checkbox "Screen Mirroring" of group 1 of group 1
perform action 1
delay 1
end tell
end if
-- ventura??
-- "Screen Mirroring" is inside a "group 1"
if exists (checkbox "Screen Mirroring" of group 1) then
tell its checkbox "Screen Mirroring" of group 1
perform action 2
delay 1
end tell
end if
end if
end tell
end tell
end tell
I'm hoping not too many things have changed between Monterey and Ventura and it'll work. Run it from the system script editor to test.
If you'd like to see my full example please go to github here. The script also is able to select a device from the Screen Mirroring dropdown.
I just got a solution working for Big Sur and Monterey about a week ago after much frustration and testing.

Related

how to set safari zoom level to 100% from the below shared image/steps with applescript or python script for macos desktop?

safari->preferences->websites->Page Zoom-> click on "when visiting other websites" and make this to 100% if option ranges in number from 50% to 200%
Need an applscript for this.
click on this to see the image where i am looking for the zoom setting to 100%
AppleScript 1: Set Safari default Page Zoom to 100%
tell application "System Events" to tell application process "Safari"
set frontmost to true
keystroke "," using command down -- Open Safari Preferences window
click button "Websites" of toolbar 1 of window 1
-- Need for seeing, selecting or clicking groups (or panes) under Websites window
tell group 1 of group 1 of window "Websites"
select row 5 of table 1 of scroll area 1 of group 1
-- group 1: left pane. row 5: Page Zoom
click pop up button of group 2
-- group 2: right pane. Revealed from the command "UI element" in AppleScript 2 below
click menu item "100%" of menu 1 of pop up button of group 2
end tell
keystroke "w" using {shift down, command down}
-- Or, keystroke "w" using command down: close Preferences window
end tell
MacOS 11.6.8 Big Sur
Explanation: see comments after -- on each lines.
Add a line "delay 1" between action command (Eg: keystroke, click and select) lines if your Mac needs.
You may script changes of Safari and other apps' Preferences in a similar way.
AppleScript 2: Find out all UI elements after some UI actions
To find out which UI elements (such as window, toolbar, button, group, scroll area, table, row, pop up button, menu, menu item) are available after some UI actions, put the command "UI element" under their parent UI element in Script Editor (NOT Automator). Eg:
tell application "System Events" to tell application process "Safari"
set frontmost to true
keystroke "," using command down
click button "Websites" of toolbar 1 of window 1 -- Need
UI element of group 2 of group 1 of group 1 of window "Websites"
end tell
Result: (below the script in Script Editor)
--> {static text "Control the page zoom level on the websites below:" ...,
group 1 ...,
pop up button 1 of group 2 of group 1 of group 1 of window "Websites" of application process "Safari" of application "System Events",
-- Useful in AppleScript 1 above
static text "When visiting other websites:" ...,
button "Remove" ...}
Attention: the action command 'click button "Websites" ...' is required to display the UI elements after it.
Note: Pls encourage new contributor and vote up if you find this answer useful. Thanks!

Applescript select all checkboxes in scroll area

I've automated printing a weekly calendar with 'applescript' and 'Calendar'. There is a scroll area with collection of checkboxes. How do you iterate over every checkbox in a scroll area and uncheck it?
https://gist.github.com/spuder/c92dd0637ce85b6960b81e1415d7c52e
This works but is fragile since the rows are hard coded.
-- Click the “<fill in title>” checkbox.
delay 0.5
set timeoutSeconds to 2.0
set uiScript to "click checkbox 1 of row 2 of outline 1 of scroll area 1 of window \"Print\" of application process \"Calendar\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” checkbox.
delay 1
set timeoutSeconds to 2.0
set uiScript to "click checkbox 1 of row 3 of outline 1 of scroll area 1 of window \"Print\" of application process \"Calendar\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” checkbox.
delay 1
set timeoutSeconds to 2.0
set uiScript to "click checkbox 1 of row 4 of outline 1 of scroll area 1 of window \"Print\" of application process \"Calendar\""
my doWithTimeout(uiScript, timeoutSeconds)
This seems like it should work but it does not uncheck any of the boxes
delay 1
set timeoutSeconds to 2.0
set uiScript to "click checkbox 1 of every row of outline 1 of scroll area 1 of window \"Print\" of application process \"Calendar\""
my doWithTimeout(uiScript, timeoutSeconds)
This works for me using the latest version of macOS Mojave
tell application "Calendar"
activate
reopen
end tell
tell application "System Events" to tell application process "Calendar"
if not (exists of window "Print") then keystroke "p" using command down
repeat while not (exists of window "Print")
delay 0.1
end repeat
set everyCheckboxRef to a reference to every checkbox of rows of outline 1 ¬
of scroll area 1 of window 1
repeat with i from 1 to count of everyCheckboxRef
set thisCheckbox to item i of everyCheckboxRef
if value of thisCheckbox is 1 then perform action "AXPress" of thisCheckbox
end repeat
end tell
The following example AppleScript code is one way to achieve the goal of unchecking all checkboxes in the Calendars section of the Print dialog box in the Calendar application:
-- # Check to see if Calendar is open and act accordingly.
if running of application "Calendar" then
-- # Calendar is already open however, make sure the main window is showing not minimized.
tell application "Calendar"
if not (visible of window "Calendar") then set visible of window "Calendar" to true
activate -- # Bring the main window forward.
end tell
else
-- # Calendar is not open, so open it.
tell application "Calendar"
activate
-- # Wait for main window before proceeding.
repeat until exists window "Calendar"
delay 0.1
end repeat
end tell
end if
-- # Open the Print dialog box.
tell application "System Events" to keystroke "p" using command down
-- # Make sure the Print dialog box is showing before proceeding.
tell application "Calendar"
repeat until exists window "Print"
delay 0.1
end repeat
end tell
-- # Uncheck all checkboxes in the Calendars scroll area of the Print dialog box.
tell application "System Events"
tell outline 1 of scroll area 1 of window "Print" of application process "Calendar"
repeat with i from 1 to (count rows)
tell row i
if (count UI element) > 0 then
click checkbox 1
end if
end tell
end repeat
end tell
end tell
Note: The example AppleScript code is just that and does not contain any additional 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. Additionally, UI Scripting may require the use of the delay command as appropriate, needed or wanted.

UI automation, appleScript Keyboard shortcuts for non-menued items Preview?

I am trying to create a keyboard shortcut action for Preview, namely Draw and Sketch. However, they are are the NON-menued items, which means can't get it done in System Preference I see someone done it from inspiration, it is possible, but when I try to follow alone, here is my code so far and please help me complete this. here are the action.
Here is the error I am facing now
after some researches, does the UI/accessibility inspector help?
activate application "Preview"
delay 0.4
set the menuItem to "Draw"
tell application "System Events"
try
tell application process "Preview" to click radio button menuItem of radio group 1 of splitter group 1 of window 1
on error
try
tell application process "Preview" to click radio button menuItem of radio group 1 of window 1
on error errorM
display dialog errorM
end try
end try
end tell
ideally, trying to make it to work when all bars are hidden,
but if not possible. can we make it to work vwith mark up bar is shown. as below.
This work for me using the latest version of macOS Mojave
tell application "Preview" to activate
repeat while application "Preview" is not running
delay 0.2
end repeat
tell application "System Events"
try
click menu item "Show Markup Toolbar" of menu 1 of menu bar item "View" of menu bar 1 of application process "Preview"
end try
delay 0.5
try
click menu item "Show Toolbar" of menu 1 of menu bar item "View" of menu bar 1 of application process "Preview"
end try
delay 0.5
repeat while not (exists of toolbar 1 of window 1 of application process "Preview")
delay 0.2
end repeat
set description2 to a reference to every checkbox of toolbar 1 of window 1 of application process "Preview"
set theCheckboxes to description of description2
if item 1 of theCheckboxes is "Draw" then
set checkBoxDraw to 1
else
set checkBoxDraw to 2
end if
if item 1 of theCheckboxes is "Sketch" then
set checkBoxSketch to 1
else
set checkBoxSketch to 2
end if
delay 1
-- Below, insert either checkBoxSketch for "Sketch" or checkBoxDraw for "Draw"
click checkbox checkBoxDraw of toolbar 1 of window 1 of application process "Preview"
end tell
-- without these next following lines, the toolbar "Draw" or "Sketch" do not appear to be selected
tell application "Preview" to tell window 1
set visible to false
set visible to true
end tell
delay 3

Applescript delay so long when run click button command

i was write a simple code to click share button on Notes applicaion
set upArrow to ASCII character 30
activate application "Notes"
tell application "System Events"
tell process "Notes"
set frontmost to true
click button 2 of group 2 of splitter group of window 1
keystroke upArrow
keystroke return
end tell
end tell
the problem is
click button 2 of group 2 of splitter group 1 of window 1 of application process "Notes" --> missing value
it need 6s to complete run this and return error missing value
but if i dont add keystroke or any command follow that, this code work perfectly
I also get that delay and it returns missing value. But could you click a menu bar item instead?
activate application "Notes"
tell application "System Events" to tell process "Notes"
click menu item "Email" of menu 1 of menu item "Share" of menu "File" of menu bar 1
end tell
set focused of button 2 of group 2 of splitter group 1 of window 1 to true
keystroke space
or
set value of attribute "AXFocused" of button 2 of group 2 of splitter group 1 of window 1 to true
keystroke space
Source:
https://lists.apple.com/archives/Accessibility-dev/2006/Oct/msg00013.html
There is a thread that seems to describe the same bug that appears to be limited to specific software. It is on MacScripter.net: Script delays on clicking button (controlling Sys Prefs pane)
Note the most recent post that describes a delay in FileMaker. It seems like the only work-around when software exhibits this bug is to do something else to open the new window. If the only way to run the desired function is via a button, one (terrible) option is clicking at coordinates relative to the corner of the front window. Obviously this will easily fail if the content can move relative to the corner or if a new version of the software moves the button desired. Any other ideas?
UPDATE, 2023-02-13:
In case anybody is still dealing with this bug, here's some useful AppleScript to get the coordinates of the object you'd like to click. You can then feed those into some coordinate-clicking utility, like cliclick (binary), Python code, Keyboard Maestro, and so on.
tell application "System Events"
set someObject to <REFERENCE TO YOUR OBJECT>
-- e.g. op's: button 2 of group 2 of splitter group of window 1 of application process "Notes"
set {xCoord, yCoord} to position of someObject
set {xSize, ySize} to size of someObject
end tell
set objOffset to round (minNum({xSize, ySize}) / 2) rounding down
set xClick to xCoord + objOffset
set yClick to yCoord + objOffset

How can I make this ApplesScript execute instantly without a 13 second delay?

I was trying to make a shortcut on OSX Mountain Lion to "Share a file" with the LogMeIn Application as one does not exist. I opened Automator and created an Application under "watch me do". I clicked record and
navigated to the menu bar and clicked on "LogMeIn">"Share a file..." and clicked "Share a file" in that dialog box and stopped recording. I then copied the commands in Automator and pasted them in AppleScript editor, hoping to change a few things to make it execute faster. I chose 10x for the speed in Automator and it still takes about 13 seconds from the time I do the shortcut. If anyone knows how to change this AppleScript to make it instant, please feel free to change it.
Any help would be appreciated.
Thanks
-- Click the “<fill in title>” menu.
set timeoutSeconds to 2.0
set uiScript to "click menu bar item 1 of menu bar 1 of application process \"LogMeIn Menubar\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Share a file...
set timeoutSeconds to 2.0
set uiScript to "click menu item \"Share a file...\" of menu 1 of menu bar item 1 of menu bar 1 of application process \"LogMeIn Menubar\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “Share a file...” button.
set timeoutSeconds to 2.0
set uiScript to "click UI Element \"Share a file...\" of group 1 of window \"LogMeIn\" of application process \"LogMeIn\""
my doWithTimeout(uiScript, timeoutSeconds)
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
That's really cool. I didn't know you could copy/paste those "watch me do" commands in AppleScript Editor. I think I'll find a use for that.
Anyway you may not be able to make your code "instant" because ui scripting just does that. However if I was writing your code as a regular applescript, here's what it would look like. Try it, maybe it will help. I can't test it because I do not have that application. Good luck.
NOTE: I made "Share a file…" as "Share a file" and an ellipsis character (option-semicolon). If you have problems try changing the ellipsis to 3 periods.
set timeoutSeconds to 2.0
tell application "LogMeIn Menubar" to activate
tell application "System Events"
tell process "LogMeIn Menubar"
click menu bar item 1 of menu bar 1
-- delay until it opens
set startTime to current date
repeat until exists menu 1 of menu bar item 1 of menu bar 1
delay 0.2
if (current date) - startTime is greater than timeoutSeconds then
error "Waited too long for menu 1 of menu bar item 1 of menu bar 1"
end if
end repeat
click menu item "Share a file…" of menu 1 of menu bar item 1 of menu bar 1
-- delay until it opens
set startTime to current date
repeat until exists group 1 of window "LogMeIn"
delay 0.2
if (current date) - startTime is greater than timeoutSeconds then
error "Waited too long for group 1 of window \"LogMeIn\""
end if
end repeat
click UI element "Share a file…" of group 1 of window "LogMeIn"
end tell
end tell

Resources