What is the order of
If two windows on your macOS desktop overlap,
which one gets shown?
Sometimes, the user can decide:
by clicking on a window, it comes to the front.
But windows also have a “level” property, which overrides this user-defined ordering.
_level property of an
NSWindow is an integer,
and if one window has a higher
_level than another,
it’s always shown in front.
You can set this raw
_level property of an
NSWindow like this:
window.level = NSWindow.Level(rawValue: 9)
However, Apple doesn’t recommend using raw integers like this.
They prefer that you use their semantic names for different levels.
Annoyingly, Apple have two parallel lists of semantic levels:
Here’s how you use
let window:NSWindow = NSWindow(/* ... */) window.level = NSWindow.Level.tornOffMenu
And here’s how you use
window.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(CGWindowLevelKey.tornOffMenuWindow)))
Both lists of semantic names are poorly documented. Most annoyingly, the Apple documentation does not say what the values are for these semantic levels, and does not even say what their relative ordering is. Even more deceivingly, the ordering of the levels listed in the documentation is not the numeric order of the levels!
However, we can find the raw levels by debugging, and they turn out to be as follows, in correct numerical order:
CGWindowLevelForKey(.baseWindow) = -2147483648 CGWindowLevelForKey(.desktopIconWindow) = -2147483603 CGWindowLevelForKey(.minimumWindow) = -2147483643 CGWindowLevelForKey(.desktopWindow) = -2147483623 CGWindowLevelForKey(.backstopMenu) = -20 NSWindow.Level.normal = CGWindowLevelForKey(.normalWindow) = 0 NSWindow.Level.floating = CGWindowLevelForKey(.floatingWindow) = 3 NSWindow.Level.submenu = 3 NSWindow.Level.tornOffMenu = CGWindowLevelForKey(.tornOffMenuWindow) = 3 NSWindow.Level.modalPanel = CGWindowLevelForKey(.modalPanelWindow) = 8 CGWindowLevelForKey(.utilityWindow) = 19 NSWindow.Level.dock = CGWindowLevelForKey(.dockWindow) = 20 NSWindow.Level.mainMenu = CGWindowLevelForKey(.mainMenuWindow) = 24 NSWindow.Level.statusBar = CGWindowLevelForKey(.statusWindow) = 25 NSWindow.Level.popUpMenu = CGWindowLevelForKey(.popUpMenuWindow) = 101 NSWindow.Level.screenSaver = 101 CGWindowLevelForKey(.overlayWindow) = 102 CGWindowLevelForKey(.helpWindow) = 200 CGWindowLevelForKey(.draggingWindow) = 500 CGWindowLevelForKey(.screenSaverWindow) = 1000 CGWindowLevelForKey(.assistiveTechHighWindow) = 1500 CGWindowLevelForKey(.cursorWindow) = 2147483630 CGWindowLevelForKey(.maximumWindow) = 2147483631
Note some oddities here:
NSWindow.Level.normalis mostly a subset of
CGWindowLevelKeydefines some more obscure levels.
- Many levels are synonyms.
NSWindow.Level.tornOffMenuare all level
- You would expect
NSWindow.Level.screenSaver == CGWindowLevelForKey(.screenSaverWindow), but they’re decidedly different.
More by Jim
- Smear phishing: a new Android vulnerability
- A probabilistic pub quiz for nerds
- Time is running out to catch COVID-19
- The inception bar: a new phishing method
- The hacker hype cycle
- Project C-43: the lost origins of asymmetric crypto
- How Hacker News stays interesting
- My parents are Flat-Earthers
- The dots do matter: how to scam a Gmail user
- The sorry state of OpenSSL usability
- I hate telephones
- The Three Ts of Time, Thought and Typing: measuring cost on the web
- Granddad died today
- Your syntax highlighter is wrong