22

I just updated to macOS Mojave, and immediately noticed a couple of things:

  • My custom login screen wallpaper is gone.
  • When you click on a user's name in the login screen, it switches to their personal background (their usual wallpaper for the first space on the primary monitor).

I assumed it had just overwritten my cached image file. But when I went to replace it, nothing happened. It turns out that com.apple.desktop.admin.png is gone entirely!

no-cached-image

Right after taking that screenshot, I decided to poke into Desktop Pictures and found my personal login screen background, which looks promising. It contains one other folder, which  probably  (edit: confirmed) contains the login screen background of my administrator account.

0

4 Answers 4

17

I've fixed it! You'll have to edit the dune HEIC picture though. If you're willing, follow these steps:

​1) Go To: /Library/Desktop Pictures/

2) Find the file called "Mojave.heic"

3) Save a copy as a backup somewhere else

4) Select the picture you want to have instead

5) Edit image values (DPI, size, etc.) to fit

6) Rename this edited picture as Mojave.heic

15
  • Good thinking, except this "removes" the Mojave background in the Desktop Background preference pane.
    – Joseph
    Sep 26, 2018 at 5:11
  • That definitely might be acceptable! I take it SIP won't trigger, since it's in /Library? And it has to be HEIF, right? Most of my images are JPEGs, so I'll have to figure out a way to convert them for this. Maybe sip.
    – SilverWolf
    Sep 26, 2018 at 13:01
  • You can just rename a whole jpg file as Mojave.heic and it works just fine.
    – Leonard
    Sep 26, 2018 at 14:41
  • @Leonard Interesting. You've tested that, and it works? I'm quite surprised, but that's fantastic!
    – SilverWolf
    Sep 27, 2018 at 16:21
  • @BlackPearl tried this, and it didn't work. I don't know all the specifics of the attempt, though.
    – SilverWolf
    Sep 27, 2018 at 16:53
6

Expanding on Leonard's answer:

You can do this by replacing the Mojave.heic default desktop background. This does not require disabling SIP, as it's in /Library.

  • Back up /Library/Desktop Pictures/Mojave.heic by copying it to Mojave.heic.orig or similar.

  • Get your new image and scale/crop it to exactly fit the display. If you don't know your screen resolution, you can go to  > About This Mac.

  • Replace Mojave.heic with your new file. Don't worry if it's JPG or similar, it'll still work even after you rename it to Mojave.heic.*

  • If you have FileVault enabled, change a login option in System Preferences. For example, whether to show a list of users or name and password fields. Just change it back if you don't actually want it changed.

    This is because when you boot with FileVault, at the login screen your system hasn't really booted up all the way! It's actually running a tiny system on your EFI partition, since your main partition is encrypted. Changing a login option will make System Preferences change the EFI system's settings, including picking up the wallpaper change. See this answer.

  • Reboot and enjoy!

* I've only tested this with JPEG images, but it may work for other types.


Completely Unnecessary Timesaver

I've made a small Swift program that does all this for you (it detects the OS version and works both on Mojave and earlier versions). You'll need Xcode to compile it.

It shouldn't break your system, but I can't guarantee anything -- make sure you have backups first!

This is now also available on GitHub. It may or may not be updated here in the future.

//
// loginwindowbgconverter
// by SilverWolf
// 2018-09-27
//

import Foundation
import AppKit

func printUsage() {
    print("""
    usage: \(CommandLine.arguments[0]) \u{1B}[4mimage-file\u{1B}[0m
    It needs to be run as root, as it saves to /Library/Desktop Pictures.
    """)
}

guard CommandLine.arguments.indices.contains(1) else {
    printUsage()
    exit(1)
}
let inputFile = CommandLine.arguments[1]

guard let inputImage = NSImage(contentsOfFile: inputFile) else {
    print("\(CommandLine.arguments[0]): can't load image from \(inputFile)")
    exit(2)
}

let iw = inputImage.size.width
let ih = inputImage.size.height
let iaspect = Double(iw) / Double(ih)

// use System Profiler to get screen size

var sw = 0, sh = 0

enum ScreenSizeError: Error {
    case foundNil
}
do {
    let task = Process()
    if #available(macOS 10.13, *) {
        task.executableURL = URL(fileURLWithPath: "/bin/zsh")
    } else {
        task.launchPath = "/bin/zsh"
    }
    task.arguments = ["-f", "-c", "system_profiler SPDisplaysDataType | awk '/Resolution/{print $2, $4}' | head -n 1"]
    
    let stdoutPipe = Pipe()
    task.standardOutput = stdoutPipe
    
    if #available(macOS 10.13, *) {
        try task.run()
    } else {
        task.launch()
    }
    task.waitUntilExit()
    
    let data = stdoutPipe.fileHandleForReading.readDataToEndOfFile()
    guard let text = String(data: data, encoding: .utf8) else {
        throw ScreenSizeError.foundNil
    }
    let sizes = (text as NSString).replacingOccurrences(of: "\n", with: "").components(separatedBy: " ")
    sw = Int(sizes[0]) ?? 0
    sh = Int(sizes[1]) ?? 0
    guard sw != 0 && sh != 0 else {
        throw ScreenSizeError.foundNil
    }
} catch {
    print("\(CommandLine.arguments[0]): can't get screen resolution")
    exit(3)
}

print("Screen size: \(sw)x\(sh)")

var nw = 0, nh = 0
var x = 0, y = 0 // offsets

let saspect = Double(sw) / Double(sh)
if saspect > iaspect { // screen is wider
    nw = sw
    nh = Int(Double(sw) / iaspect) // keep input image aspect ratio
    y = -1 * (nh - sh) / 2 // half the difference
} else { // screen is narrower
    nh = sh
    nw = Int(Double(sh) * iaspect)
    x = -1 * (nw - sw) / 2
}

// draw into new image
guard let newImage = NSBitmapImageRep(bitmapDataPlanes: nil,
                                pixelsWide: Int(sw),
                                pixelsHigh: Int(sh),
                                bitsPerSample: 8,
                                samplesPerPixel: 4,
                                hasAlpha: true,
                                isPlanar: false,
                                colorSpaceName: .deviceRGB,
                                bytesPerRow: sw * 4,
                                bitsPerPixel: 32) else {
    print("\(CommandLine.arguments[0]): can't create bitmap image to draw into!")
    exit(2)
}

NSGraphicsContext.saveGraphicsState()
let graphicsContext = NSGraphicsContext(bitmapImageRep: newImage)
NSGraphicsContext.current = graphicsContext
graphicsContext?.imageInterpolation = .high
let r = NSMakeRect(CGFloat(x), CGFloat(y), CGFloat(nw), CGFloat(nh))
print("drawing rect: \(r)")
inputImage.draw(in: r)

graphicsContext?.flushGraphics()
NSGraphicsContext.restoreGraphicsState()

print("image size: \(newImage.size)")

// write to file
if #available(macOS 10.14, *) { // macOS Mojave has a completely different system
    let targetFile = "/Library/Desktop Pictures/Mojave.heic"
    let origFile =  "/Library/Desktop Pictures/Mojave.heic.orig"
    if !FileManager.default.fileExists(atPath: origFile) { // no backup of original Mojave.heic
        print("Backing up original Mojave.heic (this should only happen once)")
        do {
            try FileManager.default.copyItem(atPath: targetFile, toPath: origFile)
        } catch {
            print("\(CommandLine.arguments[0]): \u{1B}[1mbackup failed, aborting!\u{1B}[0m \(error.localizedDescription)")
            exit(1)
        }
    }
    
    print("Saving to \(targetFile)")
    // actual writing
    let imageData = newImage.representation(using: .jpeg, properties: [:])!
    do {
        try imageData.write(to: URL(fileURLWithPath: targetFile))
    } catch {
        print("\(CommandLine.arguments[0]): can't write image data: \(error)")
        print("(are you root?)")
        exit(1)
    }
} else {
    let targetFile = "/Library/Caches/com.apple.desktop.admin.png"
    print("Saving to \(targetFile)")
    let pngData = newImage.representation(using: .png, properties: [:])!
    do {
        try pngData.write(to: URL(fileURLWithPath: targetFile))
    } catch {
        print("\(CommandLine.arguments[0]): can't write image data: \(error)")
        print("(are you root?)")
        exit(1)
    }
}

//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <https://unlicense.org/>.
//
6
  • To get the screen dimensions you can use NSScreen frame property developer.apple.com/documentation/appkit/nsscreen/1388387-frame Oct 29, 2018 at 17:37
  • I tried that. It returns the "fake" screen size used for layout, not the real, physical screen size.
    – SilverWolf
    Oct 29, 2018 at 17:40
  • And multiplying it by the backing scale factor doesn't work either: it returns a flat 2 for me, even though I'm using higher density scaling. So it can be larger or smaller than the physical size, depending on your scaling settings. (:
    – SilverWolf
    Oct 29, 2018 at 17:44
  • Ah OK, I get what you mean:) Oct 29, 2018 at 19:07
  • 1
    Unfortunately, this didn't work for me. I even tried the program but with no success. I'm still getting the default dune instead of my picture. I have FileVault enabled but I changed login option as you described. Any ideas?
    – Artem M
    Jan 4, 2019 at 22:07
1

I receive a weird image when I just replace the file with a JPG, renaming it too HEIC. However, when I take the image I want as the background and export it in the HEIC format in Preview, it all works great. I was working with a 5333×3333 image to start with:

  1. Open image you want as your background in Preview
  2. In Preview, select File > Export...
  3. Set the Format to HEIC and Quality to best (I got a completely blank image when I tried a quality less than "Best")
  4. Rename the exported file as Mojave (the extension should already be .heic)
  5. Copy exported image to /Library/Desktop\ Pictures

When you logout, you should see your new background. Try restarting, if don't see the image show up right away.

If you run into issues with exporting the file as .heic, try adjusting the size of the image using Preview: Tools > Adjust Size. As a start, set it to the size of your screen as seen in System Information > Graphics/Displays.

1
  • Thank you, good to know! Also, I wrote a small program to do all this automatically if you don't want to resize it with Preview, and it can now export to HEIF. You can find it over on GitHub.
    – SilverWolf
    May 15, 2019 at 16:32
-1

This problem is driving me crazy for months!

Here is my solution

(no FileVault activated)

My wife and I are working together in the home office since Corona. We both have MacBooks. I noticed that her Mac immediately shows her background as wallpaper for the login - but not on my Mac. So what was the difference?

After looking at the solution in the various forums, I noticed that the login screen of macOS would change immediately the default wallpaper when selecting one user out of multiple users. so if there is only one user on the Mac -> its background is displayed immediately.

So there must be something on her Mac that is missing on my Mac! :-|

Apparently it was a folder that macOS probably can't (or doesn't want to) create itself when it is deleted from the cache (Library/Cache/Desktop Pictures)

TLDR: user settings

  • Copy the UUID of your User-ID.
  • Go to "/Library/Caches/Desktop Pictures"
  • Create a new folder with your UUID. library folder
  • now you should adjust the permissions for the folder so that macOS has write permissions there enter image description here
  • If you change your background now, macOS should be able to create a "lockscreen.png" file here.

enter image description here

You must log in to answer this question.

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