Dozer icon indicating copy to clipboard operation
Dozer copied to clipboard

How to move status bar icons programmatically?

Open Mortennn opened this issue 4 years ago • 10 comments

Does anyone know how to move status bar icons programmatically?

Mortennn avatar Aug 07 '19 10:08 Mortennn

After seeing how Dozer hides icons using this:

static let hide: CGFloat = 10_000

I suppose the way to go might be some kind of AppleScript.

aonez avatar Sep 20 '19 14:09 aonez

Also would like to hide icons programmatically

shumink avatar Oct 21 '19 08:10 shumink

This might be useful: https://github.com/shergin/NSStatusBar-MISSINGOrder

AndrewMast avatar Oct 22 '19 14:10 AndrewMast

This might be useful: https://github.com/shergin/NSStatusBar-MISSINGOrder

@AndrewMast those do not respond (macOS 10.14), so that code is obsolete :(

[self respondsToSelector:statusItemWithLengthWithPrioritySelector] &&
[self respondsToSelector:insertStatusItemWithPrioritySelector]

aonez avatar Oct 25 '19 08:10 aonez

I noticed some keys in the plist preference file for apps:

Thought A: NSStatusItem Preferred Position Item-0

  • This seems to be the preferred pixel location for menu bar icons owned by the app
  • There may be more than one menu bar icon per app, Item-1, Item-2 etc.

What about reading and writing these keys in app preferences? I believe this is what macOS does when icons are rearranged using cmd+drag.

So I am thinking that even though all positions are "preferred", if Dozer manages all of these positions for all menu bar icons, then they should be granted their desired position without exception. Right?

We could read the keys to find out the preferred position of an icon, which after Dozer managed them all would be the actual position.

I have not checked how macOS refreshes the positions during cmd+drag, but it most certainly does not require app to restart themselves.

Searching GitHub for that, I found this shell script https://github.com/DaFuqtor/barhide that writes a key to an app preferences plist to hide menu bar icons.

Thought B: NSStatusItem Visible Item-0

  • boolean YES/NO
  • it even works for SystemUIServer to hide Notification Centre icon (or Airport, or Bluetooth but those can be hidden using the normal user interface).
  • the problem is that seems to require an app relaunch (kill/open) to see the change

Probably not good enough to be the way Dozer hides/shows icons.

Screen shot 2020-07-09 at 12 32 24

What do you think @Mortennn @aonez ?

gingerbeardman avatar Jul 09 '20 11:07 gingerbeardman

Great research!

So I am thinking that even though all positions are "preferred", if Dozer manages all of these positions for all menu bar icons, then they should be granted their desired position without exception. Right?

This is actually a pretty clever thought. Could work. We would probably also need to figure out which process updates the menu bar icons after we have updated the plists.

As you say, thought B requires restart, so it is sadly not an option.

As a side note, Bartender requires accessibility access, so we might need to look in that direction.

Mortennn avatar Jul 09 '20 17:07 Mortennn

Thought I'd start a list of what we may need to do:

  • list all menu bar icons
  • list parent apps of each icon using bundle id
    • there may be more than one icon per app (eg iStat Menus)
  • calculate new positions of icons
  • write positions of icons to app plists
  • trigger macOS menu bar update display with rearranged icons based on new positions
    • may involve applescript or accessibility

...there are probably more!

gingerbeardman avatar Jul 13 '20 10:07 gingerbeardman

Bartender showed me this in Big Sur:

Screen shot 2021-05-07 at 21 36 01

How do they do it?

gingerbeardman avatar May 07 '21 23:05 gingerbeardman

From what it looks like, it would appear that Bartender is indeed using some form of @gingerbeardman's "Thought A" where it manages the values of each app's NSStatusItem Preferred Position Item-n.

Prior to using Bartender to make any adjustments to an app I use which has 3 seperate NSStatusItem's, the value for each item was:

NSStatusItem Preferred Position Item-0 = 435.76 NSStatusItem Preferred Position Item-1 = 447 NSStatusItem Preferred Position Item-2 = 474.5

After changing the app's visibility setting in Bartender from the default "Show" to the new value of "Hide", those values were each immediately changed to :

NSStatusItem Preferred Position Item-0 = 20435.76 NSStatusItem Preferred Position Item-1 = 20447 NSStatusItem Preferred Position Item-2 = 20474.5 (increased by 20000)

So to "hide" the icons, it looks like they are really just moving them so far to the left on the menubar that they can't possibly be in view.

dmattera avatar May 19 '21 03:05 dmattera

@dmattera How do those positions change if you rearrange those menu bar items? Both using Bartender and not would be useful to know.

gingerbeardman avatar May 19 '21 10:05 gingerbeardman