I have the script

tell application "System Events"
    tell every desktop
        set picture to "/Users/jackson/Pictures/Backgrounds/backpic.jpg"
    end tell
end tell

That changes my desktop background to a specific image. The default is "Fill Screen," which I dislike. However, I cannot seem to script the dimensions.

Edit: the default seems to be whatever it was set to last, but I'd still like to know if you can control it from AppleScript

I read here that it might not be possible to directly script the answer (though it may have changed since then), but I was thinking there's probably some GUI scripting that could be done. Anyone have any ideas?

  • Don't know what version of OS X/macOS you're using, but in macOS High Sierra there is no GUI setting for how the wallpaper is to be displayed in reference to Full Screen, Fit to Screen, whatever etc. – user3439894 Nov 24 '18 at 18:04
  • Interesting task...so what is going to be behind your reduced size background if you do not Fill the screen ? – Ruskes Nov 24 '18 at 18:31
  • @Buscar웃 If you do fit to screen it shows a solid color where the picture isn't (e.g., you chose black and there's a black box around it or lines on the side). – Talos Potential Nov 24 '18 at 19:31
  • @user3439894 I'm on mojave, just go to screensaver. You can definitely choose options in the GUI – Talos Potential Nov 24 '18 at 19:31
  • @TalosPotential Did you give the script below a try ? – CJK Dec 15 '18 at 0:44

I pondered and researched this for some time, and with some help from this answer here, I have devised an AppleScriptObjc script that, on High Sierra at least (but should also work on Mojave), permits some customisation over the way the desktop background image is scaled to the (main) screen:

use framework "AppKit"
property this : a reference to current application

property NSWorkspace : a reference to NSWorkspace of this
property NSScreen : a reference to NSScreen of this
property NSColor : a reference to NSColor of this
property NSDictionary : a reference to NSDictionary of this

property fit : 1 -- NSImageScaleAxesIndependently (will never clip)
property centre : 2 -- NSImageScaleNone (will never clip)
property best : 3 -- NSImageScaleProportionallyUpOrDown (no clipping)
property fill : 3.1 -- NSImageScaleProportionallyUpOrDown (clipping)

property black : {0, 0, 0}
property white : {100, 100, 100}
property grey50 : {50, 50, 50}
property red : {100, 0, 0}
property green : {0, 100, 0}
property blue : {0, 0, 100}
on run
    scaleDesktopImage to fill over blue
end run
to scaleDesktopImage to scalingOption over {r, g, b} : {50, 50, 50}
    local scalingOption -- fit, centre, fill
    local r, g, b -- 0 to 100

    set clipping to false
    if scalingOption is not in [fit, centre, best, fill] then return false
    if scalingOption = fill then set clipping to true

    set sharedWorkspace to NSWorkspace's sharedWorkspace()
    set mainScreen to NSScreen's mainScreen()

    set options to {NSWorkspaceDesktopImageScalingKey:scalingOption ¬
        , NSWorkspaceDesktopImageAllowClippingKey:clipping ¬
        , NSWorkspaceDesktopImageFillColorKey:RGB(r, g, b)}

    set imageURL to sharedWorkspace's desktopImageURLForScreen:mainScreen

    set [success, E] to sharedWorkspace's setDesktopImageURL:imageURL ¬
        forScreen:mainScreen options:options |error|:(reference)

    if E = missing value then return success
    E's localizedDescription() as text
end scaleDesktopImage

on RGB(r as real, g as real, b as real)
    NSColor's colorWithCalibratedRed:r / 100 ¬
        green:g / 100 ¬
        blue:b / 100 ¬
end RGB

If you're not familiar with AppleScriptObjC, then observe the script is split into three sections: PROPERTY DECLARATIONS, IMPLEMENTATION, and HANDLERS, the first and last of which I suggest you don't try to adjust too much or at all, unless as a learning exercise.

That said, I'm sure you won't go far wrong if you decide to add your own custom colour properties to the grouping in the PROPERTY DECLARATIONS sections, each of which is simply a 3-item list specifying the red, green and blue colour components with values between 0 (zero contribution) and 100 (full contribution).

The second section of the script, headed IMPLEMENTATION, is the functional bit containing the explicitly declared (for clarity only) run handler. It's singular command is a call to the handler scaleDesktopImage, which is the line you'll be most wanting to play with to suit your needs.

It takes two forms, which I'll illustrate by example:

scaleDesktopImage to fill over blue


scaleDesktopImage to fill

In other words, specifying the colour over which the desktop image is laid (i.e. the background colour), is optional. If omitted, the background colour defaults to 50% grey. Of course, you needn't use a pre-declared property to specify the background colour; you can supply directly a list of RGB values:

scaleDesktopImage to best over {100, 25, 50}

The remaining parameter is mandatory, and there are four possible named values:

  • fit: Stretches the image to fit the desktop's width and height;
  • centre: Centres the image without enlarging, however it will reduce the size of an image that would otherwise spill outside the boundary of the desktop;
  • best: Enlarges or reduces the size of the image to occupy the maximum possible area of the desktop without going outside the desktop boundary and preserving the aspect ratio of the image, i.e. a proportional size adjustment;
  • fill: Sizes the image to cover the full area of the desktop, preserving the aspect ratio, but extending beyond the boundary of the desktop along one of its axes if necessary in order to cover the background.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .