Converting Between kCGWindowBounds and NSWindow#frame
kCGWindowBounds is a field in a dictionary returned by the CGWindowListCopyWindowInfo function. This fields lists the dimensions of a window displayed by the Quartz Window System (Mac OS X’s analogue of X11). I was trying to use this field to resize a NSWindow object that I was controlling, with the idea to create a window picker. The problem is that kCGWindowBounds’ coordinates are not the same ones as used by NSWindow’s frame property, and it took me a while to realize this. Which is why I am sharing what I found out.
Both kCGWindowBounds and NSWindow’s frame property are instances of CGRect (technically, NSWindow uses a NSRect but all literature I found says it is equivalent to CGRect). This object has two attributes; a point (origin) and dimensions (size). The difference between the CGRect returned by kCGWindowBounds and NSWindow’s frame property is that:
- kCGWindowBounds measures the origin as the top-left corner of the rectangle relative to the top-left corner of the screen
- NSWindow’s frame property measures the origin as the bottom-left corner of the rectangle relative to the bottom-left corner of the screen
So if you want to convert between the two representations of the same information, you have to do the following. It is the same conversion if you are going from kCGWindowBounds to NSWindow#frame or in the other direction.
bounds.origin.y=[[NSScreen mainScreen] frame].size.height-bounds.origin.y-bounds.size.height; |
Thanks for the information!
There’s a slight problem with this code: it won’t work correctly if there are multiple screens with different dimensions. (Think laptop with an external screen.)
It’s best to iterate through [NSScreens screens] to find the right one before adjusting the window bounds.
Good to know. I never used an external screen with my laptop, so I never bothered to check that.