0

In my cocoa application i want to take the screenshot of desktop wallpaper for Multiple screens i've found this link with this i made for single screen However, i am finding difficult for multiple screens. So how would i do it for multiple screens?

here is my code

- (NSImage*) desktopAsImageWithScreen:(NSScreen *)screen {

NSDictionary *deviceDescription = [screen deviceDescription];

CFMutableArrayRef windowIDs = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayRef allWindowIDs = CGWindowListCreate(kCGWindowListOptionOnScreenBelowWindow, kCGDesktopIconWindowLevel);

NSLog(@"min window level: %d", kCGMinimumWindowLevel);
NSLog( @"looking for windows on level: %d", kCGDesktopWindowLevel );
NSLog( @"NOt actually looking for windows on level: %d", kCGMinimumWindowLevel );
NSLog( @"NOt actually looking for windows on the dock level: %d", kCGDockWindowLevel );
if (allWindowIDs)
{

    CFArrayRef windowDescs = CGWindowListCreateDescriptionFromArray(allWindowIDs);
    for (CFIndex idx=0; idx<CFArrayGetCount(windowDescs); idx++)
    {
        CFDictionaryRef dict = CFArrayGetValueAtIndex(windowDescs, idx);
        CFStringRef ownerName = CFDictionaryGetValue(dict, kCGWindowOwnerName);
        NSLog(@"owner name = %@", ownerName);
        if (CFStringCompare(ownerName, CFSTR("Dock"), 0) == kCFCompareEqualTo )
        {
            // the Dock level has the dock and the desktop picture
            CGRect windowBounds;
            BOOL success = CGRectMakeWithDictionaryRepresentation(
                                                                  (CFDictionaryRef)(CFDictionaryGetValue(dict, kCGWindowBounds)),
                                                                  &windowBounds);

            NSRect screenBounds = screen.frame;
            CFNumberRef windowLayer = CFDictionaryGetValue(dict, kCGWindowLayer);

            //CFDictionaryGetValue(dict, kCGWindowBounds)
            NSLog(@"window bounds %f, %f, matches screen bounds? %d, on level %@",
                  windowBounds.size.width,
                  windowBounds.size.height,
                  CGRectEqualToRect(windowBounds, screenBounds),
                  windowLayer
                  );

            NSNumber* ourDesiredLevelNumber = [NSNumber numberWithInt: kCGDesktopWindowLevel - 1];
            if ( CGRectEqualToRect(windowBounds, screenBounds) && [ourDesiredLevelNumber isEqualToNumber: (__bridge NSNumber * _Nonnull)(windowLayer)] )
                CFArrayAppendValue(windowIDs, CFArrayGetValueAtIndex(allWindowIDs, idx));
        }

    }
    CFRelease(windowDescs);
    CFRelease(allWindowIDs);
}

CGImageRef cgImage = CGWindowListCreateImageFromArray( screen.frame, windowIDs, kCGWindowImageDefault);

// Create a bitmap rep from the image...
NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
// Create an NSImage and add the bitmap rep to it...
NSImage *image = [[NSImage alloc] init];
[image addRepresentation:bitmapRep];
//[bitmapRep release];

return image;

}

Any Suggestions?

Thanks in Advance!

iosdev
  • 90
  • 9
  • I'm having difficulty seeing how your question is not answered by the accepted answer on the linked question. use `CGWindowListCreate` and iterate the results which will contain all windows at the desired level regardless of screen (windows don't belong to a screen). – Brad Allred Oct 08 '18 at 15:12
  • @BradAllred I have updated my code can you tell me where i was missing. – iosdev Oct 09 '18 at 02:32
  • according to `QuartzDebug` the window level you want is `-2147483624` or `kCGMinimumWindowLevel + 19`. its possible this varies by version of macOS. If you dont want icons and such what is the difference between a screenshot and simply reading the wallpaper set for the desktops? – Brad Allred Oct 09 '18 at 14:41
  • Reading the wallpaper needs access of wallpaper location for sandboxed app. – iosdev Oct 10 '18 at 04:44
  • and a sandboxed app has privileges to read arbitrary windows? o_O – Brad Allred Oct 10 '18 at 05:42
  • @BradAllred Yes i guess i've exported and tested it was working. – iosdev Oct 10 '18 at 06:00
  • so did you try the correct window level I suggested? Your post doesn't actually say what is wrong. is something returning null unexpectedly, are you getting an error? – Brad Allred Oct 10 '18 at 15:16
  • As you suggested i kept `CFArrayRef allWindowIDs = CGWindowListCreate(kCGWindowListOptionOnScreenBelowWindow, kCGMinimumWindowLevel + 19);` it working for single screen but when comes to multiple screens it is just taking screen shot but not the desktop wallpaper. – iosdev Oct 10 '18 at 17:05
  • 1
    at this point you may want to download `QuartzDebug` and unneuter it: http://hints.macworld.com/article.php?story=20101104073546285 I am able to see both my desktop wallpapers on my dual monitor setup there. – Brad Allred Oct 10 '18 at 17:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/181646/discussion-between-iosdev-and-brad-allred). – iosdev Oct 11 '18 at 02:17

0 Answers0