Change the wallpaper on all desktops in OS X 10.7 Lion?
Asked Answered
C

1

16

I would like to change the wallpaper of all desktops (formerly "spaces") on a screen. As of OS X 10.6 there is a category to NSWorkspace which allows the setting of the wallpaper, however, when I use this function only the wallpaper of the current desktop gets changed and all the other desktops remain unchanged.

I then looked at the desktop preferences plist and wrote a class that modifies it to reflect the changes I want (basically set a new image file path). After the new file was saved I sent the com.apple.desktop "BackgroundChanged" notification - Google if you don't know what I am talking about, this was how people changed wallpapers in pre 10.6 days. At first this didn't produce any result, so instead of "nil" as userInfo dictionary I sent the exact same userInfo dictionary along as Apple does when you change the wallpaper in your settings (subscribe to the notification in an app and change the wallpaper in the settings app and you will see what it looks like). Luck helped me here, when I sent the notification this way for some reason the Dock crashed and when it reloaded, it loaded the settings from the preferences file thus displaying my changes.

This works on 10.7.1, however, I would a) rather not have the bad user experience of the dock crashing and reloading, and b) use a path that is more or less guaranteed to work in future releases as well. Exploiting a bug doesn't seem like a stable path.

Any other ideas on how to change the wallpaper of all desktops? I am also unsure whether the current behaviour of the NSWorkspace wallpaper category is intended or a bug, however, judging from the behaviour of the wallpaper preferences pane it seems that the former is the case.

Calabria answered 25/9, 2011 at 17:8 Comment(0)
L
8

There is no api for setting the same wallpaper to all screens or all spaces, NSWorkspace setDesktopImageURL it is implemented as such that it only sets the wallpaper for the current space on the current screen, this is how System Preferences does it too.

Besides the volatile method of manually modifying the ~/Library/Preferences/com.apple.desktop.plist (format could change) and using notifications to reload it (crashes you experienced) what you can do is set the wallpaper to spaces as the user switches to it , e.g. look for NSWorkspaceActiveSpaceDidChangeNotification (if your application is not always running you could tell the user to switch to all spaces he wants the wallpaper to apply to) , arguably these methods are not ideal but at least they are not volatile.

-(void)setWallpaper
{
    NSWorkspace *sws = [NSWorkspace sharedWorkspace];
    NSURL *image = [NSURL fileURLWithPath:@"/Library/Desktop Pictures/Andromeda Galaxy.jpg"];
    NSError *err = nil;
    for (NSScreen *screen in [NSScreen screens]) {
        NSDictionary *opt = [sws desktopImageOptionsForScreen:screen];        
        [sws setDesktopImageURL:image forScreen:screen options:opt error:&err];
        if (err) {
            NSLog(@"%@",[err localizedDescription]);
        }else{
            NSNumber *scr = [[screen deviceDescription] objectForKey:@"NSScreenNumber"];
            NSLog(@"Set %@ for space %i on screen %@",[image path],[self spaceNumber],scr);
        }
    }
}

-(int)spaceNumber
{
    CFArrayRef windowsInSpace = CGWindowListCopyWindowInfo(kCGWindowListOptionAll | kCGWindowListOptionOnScreenOnly, kCGNullWindowID);      
    for (NSMutableDictionary *thisWindow in (NSArray *)windowsInSpace)    {
        if ([thisWindow objectForKey:(id)kCGWindowWorkspace]){
            return [[thisWindow objectForKey:(id)kCGWindowWorkspace] intValue];
        }
    }
    return -1;
}
Lamebrain answered 1/3, 2012 at 10:25 Comment(1)
Thanks valexa, the ActiveSpaceChanged notifications are actually what I ended up using for now. Works but it's not as elegant as just being able to set them all with one commandCalabria

© 2022 - 2024 — McMap. All rights reserved.