Background
When menu bar items are rearranged manually using Cmd+drag, macOS writes a new "preferred position" preference to each app that is showing a menu bar icon. (This preference helps, but does not guarantee, that they retain their position for subsequent launches.)
Problem
I want to automate the saving of the menu bar icon positions, without interacting manually, for educational and accessibility reasons.
Question
How can I automate the repositioning of a menu bar item (which will trigger the system to write the new prefs)?
Or, how can I trigger macOS to write the new preferences directly (without automating a repositioning of a menu bar item)?
I do not want to interact with the menu items manually, or write out the preferences myself.
Best Answer
I've found a way to directly write the Preferred Position values using the shell command
defaults
. I'll leave the automation part out since I don't know the specifics of your project (I assume you know how to automate shell commands as the current user.) This should allow you to change the preferred values but won't move the menu bar items without a restart.Background
The Defaults system is used to store certain user preferences on macOS. This happens to include the Preferred Position for Menu Bar items. I'll let Apple explain the basics better:
From
man defaults
:In short, Defaults are categorized under Domains (the app or service the setting belongs to), are identified using Keys (the name of the particular setting), and each *Key has a Value assigned to it.
The Preferred Position defaults we care about are not all under one domain, since individual apps can add new items to the Menu Bar. However, the keys all share this format:
NSStatusItem Preferred Position <menu-item-name>
where
<menu-item-name>
is the name of each item a particular app or service adds.The values are all stored as
float
numbers, usually integers but some have a decimal point.Here are the macOS built-in Menu Item Defaults on my machine as an example.
com.apple.systemuiserver
is a domain containing the keyNSStatusItem Preferred Position Siri
with value61
.Listing All Current Preferred Position Defaults
In order to list all the domains, keys, and values for our Preferred Position Defaults, we can use the
defaults find
command to search for matches.The command we need in this instance is
defaults find "NSStatusItem Preferred Position"
.Reading and Writing the Value of a Given Domain & Key
In order to read the value of a given domain and key, we need to use the
defaults read
command. To write, we usedefaults write
.Here, I will read the value of the key
NSStatusItem Preferred Position Siri
at thecom.apple.systemuiserver
domain.Note that the domain and key must be enclosed in double quotes.
Here, I will change the the key
NSStatusItem Preferred Position Siri
at thecom.apple.systemuiserver
domain to the value42.7
.Note that the domain and key must be enclosed in double quotes, and the
-float
before the valueAgain, I'll leave exactly how you automate this up to you, but this can all be easily integrated into your code.
If this doesn't work out for you, here are some links to the Apple Developer AppKit docs for adding items to the Menu Bar as well as for accessing the Defaults system using objective-c and swift. Not sure if they'll be any use to you but maybe they'll set you on the right track.
https://developer.apple.com/documentation/appkit/nsstatusitem
https://developer.apple.com/documentation/appkit/nsstatusbar
https://developer.apple.com/documentation/foundation/userdefaults