Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the current wallpaper in Cocoa

I'm using this code to get the current wallpaper:

NSURL *imageURL = [[NSWorkspace sharedWorkspace] desktopImageURLForScreen:[NSScreen mainScreen]];

This works fine, but when i set a folder of pictures to be the wallpaper(As shown in the picture), the imageURL is a directory, so how can i get the current wallpaper's USURL in this situation?

enter image description here

like image 723
user615816 Avatar asked Dec 31 '12 08:12

user615816


People also ask

Where is my wallpaper saved?

By default, Windows 10 stores your wallpaper images in the “C:WindowsWeb” directory. You can access this directory very simply by clicking in the search bar in the Windows 10 taskbar and type “c:windowsweb” and hitting return. The directory will pop right up.

Where is my current desktop background stored Mac?

file in Mac HD> Library> Caches> Desktop Pictures.

How do I download my own wallpaper?

Select Settings from your home screen. Under Settings, select Wallpaper, Choose New Wallpaper. Select your Photos folder, and then the saved desktop images. Select Set.

How do I put a picture on my Mac desktop folder?

STEP 1: Open a Finder window. STEP 2: Press [Command] + [Shift] + [G]. STEP 3: In the dialog that will appear, type “/Library/Desktop Pictures/” then press [Enter] or hit the Go button. NOTE: The Finder window will open to the Desktop Pictures folder, where you can add, edit, and remove files that are contained inside.


2 Answers

I've been trying to do the exact same thing. You can get the current desktop picture URL by:

  1. Getting the current space UUID from the com.apple.spaces property list,
  2. Searching the com.apple.desktop property list for the matching space,
  3. Extracting the URL from the LastName property

I am still working on this, but the following code obtains the correct URL... sometimes. The main problem is that the property lists aren't updated frequently enough, and I haven't been able to force them to refresh (short of killing the dock). Let me know if you figure something out!

NSDictionary *spacesPLIST = (__bridge NSDictionary *)(CFPreferencesCopyAppValue(CFSTR("SpacesConfiguration"), CFSTR("com.apple.spaces")));
NSDictionary *desktopPLIST = (__bridge NSDictionary *)(CFPreferencesCopyAppValue(CFSTR("Background"), CFSTR("com.apple.desktop")));

NSArray *monitors = [spacesPLIST valueForKeyPath:@"Management Data.Monitors"];
NSInteger monitorIndex = 0;
if ([monitors count] > 1) {
    //search for main (or ask user to select)
}
NSDictionary *monitor = [monitors objectAtIndex:monitorIndex];
NSDictionary *spaces = [desktopPLIST valueForKey:@"spaces"];
NSString *currentSpaceUUID = [monitor valueForKeyPath:@"Current Space.uuid"];
NSDictionary *currentSpace = [spaces valueForKey:currentSpaceUUID];
NSURL *desktopPicturesDirectory = [NSURL fileURLWithPath:[currentSpace valueForKeyPath:@"default.ChangePath"] isDirectory:true];
NSString *desktopPictureName = [currentSpace valueForKeyPath:@"default.LastName"];
NSURL *desktopPictureURL = [NSURL URLWithString:desktopPictureName relativeToURL:desktopPicturesDirectory];
[[NSWorkspace sharedWorkspace] selectFile:[desktopPictureURL path] inFileViewerRootedAtPath:@""];
like image 151
Daniel Vogelnest Avatar answered Sep 27 '22 17:09

Daniel Vogelnest


There is another way to get the image by taking a screenshot of the current wallpaper.

extension NSImage {

    static func desktopPicture() -> NSImage {

        let windows = CGWindowListCopyWindowInfo(
            CGWindowListOption.OptionOnScreenOnly,
            CGWindowID(0))! as NSArray

        var index = 0
        for var i = 0; i < windows.count; i++  {
            let window = windows[i]

            // we need windows owned by Dock
            let owner = window["kCGWindowOwnerName"] as! String
            if owner != "Dock" {
                continue
            }

            // we need windows named like "Desktop Picture %"
            let name = window["kCGWindowName"] as! String
            if !name.hasPrefix("Desktop Picture") {
                continue
            }

            // wee need the one which belongs to the current screen
            let bounds = window["kCGWindowBounds"] as! NSDictionary
            let x = bounds["X"] as! CGFloat
            if x == NSScreen.mainScreen()!.frame.origin.x {
                index = window["kCGWindowNumber"] as! Int
                break
            }
        }

        let cgImage = CGWindowListCreateImage(
            CGRectZero,
            CGWindowListOption(arrayLiteral: CGWindowListOption.OptionIncludingWindow),
            CGWindowID(index),
            CGWindowImageOption.Default)!

        let image = NSImage(CGImage: cgImage, size: NSScreen.mainScreen()!.frame.size)
        return image
    }        
}

This approach looks much simpler IMHO, if you need the picture, not the url.

Note that wallpaper is no longer defined in the com.apple.dektop plist: starting from Mavericks, the setting is moved to ~/Library/Application Support/Dock/desktoppicture.db. This is SQLite file, and the "data" table contains the url.

like image 43
Alexey Kvasov Avatar answered Sep 27 '22 18:09

Alexey Kvasov