Cocoa Screen Capture with Multiple Screens

In my recent Snipposé project I ran into a bug in my code when using CGWindowListCreateImage.

I had assumed that the GCRect for the screenBounds parameter was relative to the frame of the screen of the window I was calling convertToScreen on. It is not. It's relative to the bounds of this function: CGDisplayBounds(CGMainDisplayID()).

As usual, the coordinate space is inverted from the window so you need to flip it. The following snippet shows the code to grab a screen capture using a rect relative to a window:

// "rect" is the frame to capture in the coordinates of "window"

let mainDisplayBounds = CGDisplayBounds(CGMainDisplayID())
var captureRect = NSRectToCGRect(window.convertToScreen(rect))
captureRect.origin.y = mainDisplayBounds.height - captureRect.origin.y - captureRect.height
if let image = CGWindowListCreateImage(captureRect, .optionOnScreenBelowWindow, CGWindowID(window.windowNumber), []) {
    let screenImage = NSImage(cgImage: image, size: rect.size)
    // do something with your image, now
}        
Home