Accesing third party menu extras (menulets) via applescript? - macos

Is it possible to access third party menulets via applescript? (Those icons displayed in the top right corner of the global menu bar).
I basically want to know if a certain menu item (that is shown when you click the icon) is enabled or disabled (greyed out).
Any resources on this?
Thanks

Yes, menu items have an "enabled" property. That property is false for "greyed out" menu items. So for example, I show the clock menulet in my main menu bar. If I wanted to know the enabled property of each of its menu items I could do this...
tell application "SystemUIServer" to activate
set theProps to {}
tell application "System Events"
tell process "SystemUIServer"
set menulets to menu bar items of menu bar 1
repeat with aMenu in menulets
if (description of aMenu) is "clock" then
click aMenu -- we have to open it to access the menu items inside it
delay 0.2
set clockMenuItems to menu items of menu 1 of aMenu
repeat with aMenuItem in clockMenuItems
set end of theProps to {title of aMenuItem, enabled of aMenuItem}
end repeat
end if
end repeat
end tell
end tell
return theProps
Note that some of those menulets are not regular menulets. Those you have to treat differently but the concept is the same. You click the menulet then access its menu items and check their enable property.

Related

AppleScript to make the display black and white for monteray

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

Applescript menu bar item toggle if title of attribute is... (or exists)

I need a applescript that clicks a menu item if the title of the item has a specific name.
Here the concrete case (Sorry... I'm not allowed to embed pictures yet, so please click):
If the menu item 2 is "Enable calibration" it should be clicked. If the title is "Disable calibration" it should stop (I just put a "false" for testing in the code).
Here my first code but it doesn't work (Syntaxerror):
tell application "System Events" to tell process "SoundID Reference"
if the title of the attribute "AXMenuItem" is "Disable calibration" then click it
else
return false
end if
end tell
My second try was with the code "exists" but it doesn't work as well (just nothing happens):
tell application "System Events" to tell process "SoundID Reference"
if menu item "Enable calibration" of menu 1 exists then click it
end tell
So any advices how I could solve this?
Finally I found another solution how to solve this problem with the "try"-command:
tell application "System Events" to tell process "SoundID Reference"
tell menu bar item 1 of menu bar 2
try
click menu item "Enable calibration" of menu 1
end try
end tell
end tell

Setting a Popup Buttons Value from Applescript

I'm trying to set an external applications settings with an applescript. I currently have
tell application "System Events"
tell process "Pro Tools"
click menu item "Save Copy In..." of menu "File" of menu bar 1
tell pop up button 4 of window "Save Copy In..."
click
set value to "AIFF"
end tell
end tell
end tell
But nothing happens at the set value point. Any help would be gratefully received! Attached is a screenshot of where I'm stuck at.
I think you just need to wait until the "Save Copy In..." window appears. Try this code, which adds a delay loop looking for the window.
tell application "System Events"
tell process "Pro Tools"
tell menu bar 1's menu "File"
click menu item "Save Copy In..."
end tell
repeat until (exists window "Save Copy In...")
delay 0.1
end repeat
tell window "Save Copy In..."'s pop up button 4
click
-- the menu does not appear inthe PUB's view heirarchy until after it's clicked
tell menu 1
click menu item "AIFF" -- 'pick' should work too
end tell
end tell
end tell
end tell
Try to insert a short delay to make sure the menu is available and rather than setting the value pick the menu item.
tell application "System Events"
tell process "Pro Tools"
click menu item "Save Copy In..." of menu "File" of menu bar 1
tell pop up button 4 of window "Save Copy In..."
click
delay 0.2
pick menu item "AIFF" of menu 1
end tell
end tell
end tell
The command pick is not documented, it's a synonym of click.

How to get the number of items in a pop-up menu without opening it using applescript?

I want to write a script which saves the images in few formats. the thing is the formats are shown based on some condition. I means some times there will be 5 formats and sometimes 8. I want to completely automate the working of these saving things. So i decided to write an applescript. Got UI browser and using that I can access each and every pop-up menus. I'm using loops to perform save operation. The thing is I am not getting where to end. So i came up with a thought that if i can get the number of items in the pop-up menu then it will be easy for me to carry out the task.
Can anyone help me out?
Well this is possible but you can't count the menu items directly. Communication is at the GUI-end and not directly to the application which means that the menu needs to appear before you can count it.
tell application "System Events"
tell process "Your application"
--we need to menu to appear first
click pop up button 1 of window 1
--now the menu appeared we can count the items in it
count menu items of menu 1 of pop up button 1 of window 1
--now hide the menu again by pressing escape
key code 53
end tell
end tell
Well counting is one way to check the menu but the other way is get all the values in it and then click the right menu item by it's name. This is, maybe not in your case, in general the best solution.
set menuItemToSelect to "Title of menu item I prefer to check"
tell application "System Events"
tell process "Your Application"
tell pop up button 1 of window 1
--Only continue if the menu item isn't already selected
if value of it is not equal to menuItemToSelect then
--we need to menu to appear first
click it
--now the menu appeared we can get the items
set menuItemTitles to name of menu items of menu 1
--check if the menu item exists
if menuItemToSelect is in menuItemTitles then
--menu item exists; click on it
click menu item menuItemToSelect of menu 1
else
--the menu item to select doesn't exist; hide the menu
key code 53
end if
end if
end tell
end tell
end tell

In Applescript, how can I find out if a menu item is selected/focused?

I have a script for OS X 10.5 that focuses the Search box in the Help menu of any application. I have it on a key combination and, much like Spotlight, I want it to toggle when I run the script. So, I want to detect if the search box is already focused for typing, and if so, type Esc instead of clicking the Help menu.
Here is the script as it stands now:
tell application "System Events"
tell (first process whose frontmost is true)
set helpMenuItem to menu bar item "Help" of menu bar 1
click helpMenuItem
end tell
end tell
And I'm thinking of something like this:
tell application "System Events"
tell (first process whose frontmost is true)
set helpMenuItem to menu bar item "Help" of menu bar 1
set searchBox to menu item 1 of menu of helpMenuItem
if (searchBox's focused) = true then
key code 53 -- type esc
else
click helpMenuItem
end if
end tell
end tell
... but I get this error:
Can’t get focused of {menu item 1 of menu "Help" of menu bar item "Help" of menu bar 1 of application process "Script Editor" of application "System Events"}.
So is there a way I can get my script to detect whether the search box is already focused?
I solved my problem by working around it. I still don't know how to check if a menu item is selected though, so I will leave this topic open.
You need to use attribute AXMenuItemMarkChar.
Example:
tell application "System Events"
tell process "Cisco Jabber"
set X to (value of attribute "AXMenuItemMarkChar" of menu item "Available" of menu "Status" of menu item "Status" of menu "File" of menu bar item "File" of menu bar 1) is "✓" -- check if Status is "Availible"
end tell
end tell
If the menu item is checked, the return value is ✓, otherwise it is missing value.
Note: This test only works if the application whose menus are being inspected is currently frontmost.
The built in key shortcut Cmd-? (Cmd-Shift-/) already behaves like this. It moves key focus to the help menu's search field if it is not already focused, and otherwise dismisses the menu.
Using /Developer/Applications/Utilities/Accessibility Tools/Accessibility Inspector.app you can use the built-in accessibility system to look at properties of the UI element under the mouse. Take special note of the cmd-F7 action to lock focus on an element and the Refresh button. Sadly the element and property names don't directly match those in the script suite, but you can look at the dictionary for System Events or usually guess the right terminology.
Using this you can determine two things. First, the focused property isn't on the menu item, but rather there is a text field within the menu item that is focused. Second, the menu item has a selected property.
With this, I came up with:
tell application "System Events"
tell (first process whose frontmost is true)
set helpMenuItem to menu bar item "Help" of menu bar 1
-- Use reference form to avoid building intermediate object specifiers, which Accessibility apparently isn't good at resolving after the fact.
set searchBox to a reference to menu item 1 of menu of helpMenuItem
set searchField to a reference to text field 1 of searchBox
if searchField's focused is true then
key code 53 -- type esc
else
click helpMenuItem
end if
end tell
end tell
Though this still doesn't work. The key event isn't firing as far as I can tell, so something may still be hinky with the focused property on the text field.
Anyway, your click again solution seems much easier.
I just came across the need to do this myself for some file processing in Illustrator.
Here is what I came up with:
tell application "Adobe Illustrator"
activate
tell application "System Events"
tell process "Illustrator"
set frontmost to true
set activeMenuItem to enabled of menu item "Unlock All" of menu "Object" of menu bar item "Object" of menu bar 1
if activeMenuItem is true then
tell me to beep 3
else
tell me to beep 2
end if
end tell
end tell
end tell
Done.
This worked with no problem and could be used to iterate a file. I'll probably have to do this many more times in my future automation.
Good luck!
This worked for me to toggle between two menu items, based on which one is selected, using the "selected" property:
tell application "System Preferences"
reveal anchor "keyboardTab" of pane "com.apple.preference.keyboard"
end tell
tell application "System Events" to tell process "System Preferences"
tell pop up button 2 of tab group 1 of window 1
click
delay 0.2
set appControl to menu item "App Controls" of menu 1
set fKeys to menu item "F1, F2, etc. Keys" of menu 1
if selected of appControl is true then
click fKeys
else
click appControl
end if
end tell
end tell

Resources