Skip to content

API reference

Inside a bundle, your code talks to the app through window.DesktopOverlaysAPI. The API is split into namespaces. Each namespace is only present if you request its permission in the manifest. If you do not request a scope, the namespace is undefined, so guard for it or rely on your declared permissions.

js
const api = window.DesktopOverlaysAPI
if (api.audio) api.audio.onUpdate(frame => { /* ... */ })

Methods that return data return a Promise. Methods named onUpdate (and similar) take a callback and keep calling it as the data changes.

Namespaces at a glance

NamespacePermissionPurpose
audiosdk.audioSystem audio FFT frames.
mediasdk.mediaThe now-playing track.
windowssdk.windowsOpen windows and desktop state.
appsdk.appForeground app, fullscreen, display, desktop.
notificationssdk.notificationsWindows notifications.
optionssdk.optionsThe user's settings for this overlay.
contentsdk.contentMessages between the bundle's surfaces.
sizesdk.sizeRead and set the overlay size.

audio

Requires sdk.audio. Provides frequency data captured from system audio output, suitable for visualizers.

audio.onUpdate(callback)

Calls callback(frame) for each new frame, where frame is a Uint8Array of FFT magnitudes. The byte values match the classic getByteFrequencyData output (dB range -100 to -30, smoothing 0.8). Capture starts when the first bundle subscribes and stops when the last one unsubscribes, so there is no cost when nobody is listening.

js
const bars = document.querySelectorAll('.bar')
api.audio.onUpdate((frame) => {
  bars.forEach((bar, i) => {
    bar.style.height = (frame[i] / 255 * 100) + '%'
  })
})

media

Requires sdk.media. Reports the Windows now-playing session.

media.get()

Returns a Promise of the current snapshot, or a snapshot with hasSession: false when nothing is playing.

media.onUpdate(callback)

Calls callback(info) whenever the now-playing session changes.

The snapshot shape:

FieldTypeNotes
hasSessionbooleanFalse when there is no media session.
titlestring
artiststring
albumTitlestring
albumArtiststring
trackNumbernumber
albumTrackCountnumber
genresstring[]
playbackStatusstring
isPlayingboolean
appIdstringThe source app.
positionnumberPlayback position.
durationnumberTrack length.
lastUpdatedMsnumberWhen position was last refreshed.
thumbnailstring or nullA data:image/...;base64,... URI of the album art, or null.

Position and timeline only refresh on a seek or a track change. For a live position, interpolate from lastUpdatedMs while isPlaying is true.

js
const snap = await api.media.get()
if (snap.hasSession) title.textContent = snap.title + ' - ' + snap.artist

windows

Requires sdk.windows. Reports open top-level windows and whether the desktop is showing. The app's own overlay windows are excluded from the list.

windows.get()

Returns a Promise of the currently visible top-level windows as WindowInfo[]. Visible means not minimized, not cloaked, and having a title.

windows.getForeground()

Returns a Promise of the current foreground window as WindowInfo, or null on the desktop.

windows.onUpdate(callback)

Calls callback({ windows, foreground, desktop }) whenever the set of windows or the foreground changes. desktop is the same boolean as $.app.desktop in conditions: true when no application window is visible.

WindowInfo shape:

FieldType
titlestring
exestring
xnumber
ynumber
widthnumber
heightnumber
foregroundboolean

app

Requires sdk.app. Gives you the same $.app state that conditions use, readable at runtime.

app.get()

Returns a Promise of { activeProcess, fullscreen, displayId, desktop }. activeProcess is the lowercase foreground executable name, or null on the desktop. displayId is the display this overlay sits on.

app.onUpdate(callback)

Calls callback(state) with the same shape whenever the foreground or desktop state changes, so the bundle can react to the same conditions it declares.

notifications

Requires sdk.notifications. Reports Windows notifications from the Action Center. On first use, Windows asks the user to allow reading notifications. If the user declines, the list comes back empty.

notifications.get()

Returns a Promise of the current notifications as NotificationInfo[], oldest first.

notifications.getLast()

Returns a Promise of the newest notification as NotificationInfo, or null.

notifications.onUpdate(callback)

Calls callback(list) with the full current list whenever a notification is added, updated, or removed.

NotificationInfo shape:

FieldType
idstring
appIdstring
appNamestring
titlestring
bodystring
timestampnumber

options

Requires sdk.options. Reads the user's settings for this overlay instance and reacts to changes. See Options for how to define them.

options.get()

Returns a Promise of the current values, keyed by option key.

options.set(key, value)

Sets one option value.

options.update(values)

Sets several option values at once, given an object of key to value.

set and update cannot change shortcut or file options. Those are user-driven only, and writes to them are ignored.

options.onUpdate(callback)

Calls callback(event) when something changes. The event.action field tells you what happened:

actionExtra fieldsMeaning
value-changevaluesOne or more option values changed. values holds the changed keys.
button-clickkeyA button option was clicked.
shortcutkeyA shortcut option's global key was pressed.
editor-statevisible, editModeThe overlay's editor state changed. visible is whether the overlay is shown; editMode is whether the editor panel is open.

The initial state is also sent once when the surface loads.

js
api.options.get().then(apply)
api.options.onUpdate((e) => {
  if (e.action === 'value-change') apply(e.values)
  else if (e.action === 'button-click') doAction(e.key)
})

content

Requires sdk.content. Lets the bundle's own surfaces talk to each other. A message is delivered to every other open surface of the same bundle, but not back to the sender.

content.sendMessage(message)

Sends a message object to the bundle's other open surfaces.

content.onMessage(callback)

Calls callback(message) for messages from the bundle's other surfaces.

size

Requires sdk.size. Reads and changes the overlay's box size.

size.get()

Returns a Promise of { width, height } in pixels.

size.set(width, height)

Resizes the overlay. Expects positive integers. The change is saved and reflected everywhere. For fullscreen surfaces the effect is limited, since they cover the display.

js
const s = await api.size.get()
api.size.set(s.width, s.height + 40)