Prompted by a tweet by NSHipster, and a subsequent thread, I wanted to find out how Mojave dynamic wallpapers worked. NSHipster and ole reverse engineered the file format. In the Twitter thread, NSHipster mentions an edge case: What happens above 66ºN (latitude)?
The first thing to do was find out what process handles the wallpaper on macOS. I primarily do iOS research, and honestly had no idea. I opened Console, searched for "solar", and then changed my static wallpaper to a dynamic one. Voila!
Message: index: 7 next: 14815.999366
Process: Dock
Image: DynamicDesktop
Category: solar
Domain: com.apple.dynamicdesktop
otool -L /System/Library/PrivateFrameworks/DynamicDesktop.framework/DynamicDesktop
confirms my suspicions that the GeoServices framework is being used for solar calculations (used on iOS by Home app and backboardd for sunrise and sunset, and on watchOS for the Solar watch face and the lunar complication).
I wrote a test program to find out what GeoServices says sunrise and sunset is at problematically high latitudes. The magic latitude was 86.2ºN. Once 86.21º was hit, the NSDate
s for the rise
and set
properties of GEOCelestialEphemeris
were nil
.
NSHipster followed up with a reasonable question: "[D]oes that mean that our friends at the ends of the Earth are indeed left in the dark with Dynamic Desktop?" To answer this, we need to have a look at the code. How does Apple handle these edge cases?
Using the Spherical Cap formula, we get
4.1581e+6
square miles. Google has the radius of Earth at3,959 mi
. I calculated the height by usingradius - (radius/90 * 86.2)
(seems sound, please comment below, or tweet at me if you think otherwise). This comes out to 2.1% of Earth's total surface area. We need to multiply this by two though, to get the South Pole: 4.2% of Earth's total surface area is not supported by GEOCelestialEphemeris.
Opening up the private DynamicDesktop framework in Hopper, the first thing I noticed is that it's written in Swift. This isn't relevant to this write-up, however I wanted to note it, because I rarely see Swift in frameworks shipped with iOS.
I'm writing as I'm going through this process. I just realized a mistake I made: The write-ups by Ole and NSHipster mention the altitude and azimuth. The API I tested is for getting sunrise and sunset times, and I was assuming some simple math would be applied to get the altitude. Obtaining the azimuth in this manner is not feasible. The code in DynamicDesktop confirms that.
The test program I mentioned above used the GEOCelestialEphemeris class. DynamicDesktop uses GEOHorizontalCelestialBodyData, which has two properties: altitude
and azimuth
. Gently hits head. An updated test program will be attached below.
DynamicDesktop is the framework responsible for dynamic wallpapers. It uses the GEOHorizontalCelestialBodyData
class from GeoServices, a framework used on macOS, iOS, and watchOS to power various features. The altitude and azimuth of the sun is able to be calculated for any latitude on Earth.
Can you give a link to an example file for
apr
type