Skip to content

Files & Directories

Wallpaper Engine and the development simulator expose the same callbacks but cannot expose local files in the same way. Normalize a received path at the point where it becomes a browser URL.

import { toFileUrl } from 'wallpaper-engine/helpers';
image.src = toFileUrl(properties.background.value);

toFileUrl() prefixes a native path such as C:/Wallpapers/image.png with file:///. It preserves empty strings, root-relative paths, and existing http:, https:, data:, blob:, or file: URLs.

const background = fileProperty({
text: 'Background image',
value: '',
fileType: 'image',
});

fileType: 'image' | 'video' asks the editor and simulator to filter selectable files. The runtime wrapper is { value: string }.

Environment Value shape Browser use
Wallpaper Engine Native filesystem path Pass through toFileUrl() to add file:///
Development simulator Local blob: object URL Pass through toFileUrl(); it remains unchanged

The simulator does not upload the selected file or disclose its filesystem path. The browser creates a page-local object URL. The simulator revokes URLs when selections are replaced or cleared and on page unload; application code must not persist those URLs across reloads.

A directory property requires one delivery mode:

const randomImages = directoryProperty({
text: 'Random images',
value: '',
fileType: 'image',
mode: 'ondemand',
});
const gallery = directoryProperty({
text: 'Gallery',
value: '',
fileType: 'image',
mode: 'fetchall',
});

The property callback’s value is the selected directory path. Route files through the callbacks for that mode.

Mode Request Delivery Application state
ondemand wallpaperRequestRandomFileForProperty(key, callback) One property name and file path Current random file
fetchall No request userDirectoryFilesAddedOrChanged and userDirectoryFilesRemoved Collection keyed by property name
function requestRandomImage(): void {
window.wallpaperRequestRandomFileForProperty(
'randomimages',
(propertyName, filePath) => {
if (propertyName !== 'randomimages')
return;
randomImage.src = toFileUrl(filePath);
},
);
}

Request after the directory property becomes non-empty and whenever the application wants another random file. An empty path means no file is currently available; handle it without constructing a URL.

const filesByProperty = new Map<string, Set<string>>();
window.wallpaperPropertyListener = {
userDirectoryFilesAddedOrChanged(propertyName, changedFiles) {
const files = filesByProperty.get(propertyName) ?? new Set<string>();
for (const path of changedFiles) files.add(path);
filesByProperty.set(propertyName, files);
},
userDirectoryFilesRemoved(propertyName, removedFiles) {
const files = filesByProperty.get(propertyName);
if (!files)
return;
for (const path of removedFiles) files.delete(path);
},
};

Convert a path with toFileUrl() only when assigning it to an image, video, or fetch operation. Keeping native paths as collection identities lets removal callbacks match the original values.

selection changes
├─ file property ───────────────→ partial user-property callback → render URL
├─ ondemand directory selected ─→ request random file → callback → render URL
└─ fetchall directory selected ─→ add/change callbacks → collection
remove callbacks → collection cleanup

In the simulator, changing a local file or directory selection also revokes obsolete blob: URLs. On the host, Wallpaper Engine owns native-path availability.

fileType filters images or videos. The simulator applies extension-based filtering to locally selected files; Wallpaper Engine owns its editor filtering rules. Always tolerate an empty collection and files that become unavailable between selection and use.

For official host semantics, see Wallpaper Engine’s custom property documentation.

Property contracts live in src/types/project.ts, host callbacks in src/types/window.ts, and normalization in src/helpers.ts.

Use Host Listeners to centralize callback ownership and Files, LED & Frames for the exact toFileUrl() contract.