Skip to content

Taskbar Tray API ​

English API reference for the taskbar, tray family.

This page is the primary owner for the namespaces listed below. Method names, parameter keys, and return fields follow the C++ RegisterApi handlers.

taskbar ​

taskbar.flash ​

Flashes the taskbar button to draw attention.

ParameterTypeRequiredDescription
countintegerNoNumber of flashes. Default 3.
intervalintegerNoMilliseconds between flashes. Default 0.

Returns: {"success":true}

js
await fb2k.invoke('taskbar.flash', { count: 3 });

taskbar.setOverlayIcon ​

Draws a small overlay badge on the taskbar button.

ParameterTypeRequiredDescription
descriptionstringNoAccessibility text for the overlay.
iconstringNoRaw Base64-encoded .ico file bytes, without data: or base64: prefixes. Empty, null, or omitted clears the overlay icon.

Returns: {"success":true}

js
// icoBase64: raw Base64-encoded .ico file bytes
await fb2k.invoke('taskbar.setOverlayIcon', { icon: icoBase64, description: 'Paused' });

// clear the overlay
await fb2k.invoke('taskbar.setOverlayIcon', { icon: '' });

taskbar.setProgress ​

Sets the taskbar button's progress bar state and fill.

ParameterTypeRequiredDescription
statestringNoOne of none, indeterminate, normal, error, paused. Defaults to none, which is also used for any other value.
valuenumberNoFill fraction. Applied only when it is a number between 0 and 1 inclusive.

Returns: {"success":true}

js
await fb2k.invoke('taskbar.setProgress', { state: 'normal', value: 0.42 });

Runtime lifecycle, menu data, and events ​

The taskbar.* and tray.* families require a standalone main window. In a panel, each handler returns { success: false, panelMode: true }. Create the icon with tray.create before relying on tray visibility, callbacks, or menu operations. Windows accepts no more than seven thumbnail buttons; a thumbnail install can also fail before the taskbar initializes its COM integration.

taskbar.setProgress accepts none, indeterminate, normal, error, or paused. A numeric value is consumed only when it is within 0–1. Thumbnail button activation broadcasts taskbar:buttonClicked with { id }.

Tray menus are configured by tray.setContextMenu and can subsequently be updated with tray.appendMenuItems, tray.removeMenuItems, tray.clearMenuItems, and tray.setMenuItemState. tray:menuItemClicked normally contains { id }; rating, slider, and segmented controls also supply value. Items executed natively by the plugin do not fire this event: the built-in showPlaybackControls / showSystemItems injections and any item declaring playbackAction run their command directly. The icon events are tray:click with { button, x, y }, tray:doubleClick with { x, y }, and tray:beforeContextMenu with { x, y }. The last event is asynchronous: changes made by a handler affect a later menu opening rather than the menu already being constructed.

The menu may use data:image/... cover data and optional webview rendering. For the webview renderer, the configured stylesheet can contain declarations such as display:flex, flex-direction:column, and background:rgba(...). The tray click event for ordinary user items is tray:menuItemClicked; it does not substitute the unrelated menu:select or menu:dismiss events. Items that the plugin executes natively — the built-in injections and any item declaring playbackAction — do not emit tray:menuItemClicked.

Reserved system items ​

showSystemItems (default true) injects two natively-executed items into the bottom zone, in this order:

IdLabelAction
_sys_showShow Main WindowRestores and foregrounds the main window, preserving its maximized / normal placement.
_sys_exitExit foobar2000Quits the application, bypassing setCloseToTray.

Both run natively and therefore do not fire tray:menuItemClicked. This is load-bearing for _sys_show: hiding to the tray applies put_IsVisible(FALSE) plus a deep suspend to the main page, so a tray:menuItemClicked handler cannot run to call window.focus itself. A frontend-event route would be dead in exactly the state the item exists for.

To render your own row instead of the injected one, use the exact, case-sensitive id _sys_show (or _sys_exit). It receives the same native route, your label / icon are preserved, and the matching injection is skipped. Lookalike ids such as _sys_show_alt or _SYS_SHOW stay ordinary user items and do not suppress the injection.

Top-level taskbar and tray icon fields are not generic image inputs. Non-empty values must be raw Base64-encoded .ico file bytes, without a Data URL header or base64: marker. PNG, JPEG, SVG, and Data URL payloads are not decoded by the ICO loader. Invalid taskbar button icons may fall back to a default icon; an invalid overlay may behave like a cleared icon; invalid tray icons fall back to the foobar2000 main icon.

js
fb2k.on('taskbar:buttonClicked', ({ id }) => console.log(id));
fb2k.on('tray:click', ({ button, x, y }) => console.log(button, x, y));
fb2k.on('tray:doubleClick', ({ x, y }) => console.log(x, y));
fb2k.on('tray:beforeContextMenu', ({ x, y }) => console.log(x, y));
fb2k.on('tray:menuItemClicked', ({ id, value }) => console.log(id, value));
fb2k.on('playback:stateChanged', () => {});
fb2k.on('playback:time', () => {});
fb2k.on('playback:trackChanged', () => {});

taskbar.setThumbnailButtons ​

Installs the thumbnail toolbar shown on the taskbar preview.

ParameterTypeRequiredDescription
buttonsarrayYesUp to seven button objects. Each optional icon uses raw Base64-encoded .ico file bytes without a prefix.

Returns: {"error":"...","success":true}

More than seven entries fails the whole call with too many thumbnail buttons; Windows allows at most 7; the list is never truncated. A missing or non-array buttons fails with buttons array required.

js
await fb2k.invoke('taskbar.setThumbnailButtons', {
    buttons: [
        { id: 'prev', tooltip: 'Previous' },
        { id: 'pp', tooltip: 'Play / Pause' },
        { id: 'next', tooltip: 'Next' },
    ],
});

taskbar.updateButton ​

Updates one already-installed thumbnail button.

ParameterTypeRequiredDescription
idstringYesId of the button to update, as passed to taskbar.setThumbnailButtons.
enabledbooleanNoWhether the button accepts clicks.
iconstringNoRaw Base64-encoded .ico file bytes without a prefix. Empty, null, or omitted supplies an empty icon value.
tooltipstringNoHover text.
visiblebooleanNoWhether the button is shown.

Returns: {"error":"...","success":true}

An empty or missing id fails with id required.

js
await fb2k.invoke('taskbar.updateButton', { id: 'pp', tooltip: 'Pause' });

tray ​

tray.appendMenuItems ​

Appends rows to an existing tray menu zone.

ParameterTypeRequiredDescription
itemsarrayYesRows to append. A missing or non-array value fails with items array required.
positionstringNoTarget zone: top, playback, or bottom. Defaults to top, which is also used for any other value.

Returns: {"error":"...","success":true}

js
await fb2k.invoke('tray.appendMenuItems', {
    items: [
        { id: 'rescan', label: 'Rescan library' },
        { type: 'separator' },
    ],
    position: 'bottom',
});

tray.clearMenuItems ​

Removes user rows from a tray menu zone.

ParameterTypeRequiredDescription
positionstringNoZone to clear: top, playback, or bottom. Omit to clear every zone.

Returns: {"success":true}

js
// clear one zone
await fb2k.invoke('tray.clearMenuItems', { position: 'top' });

// clear all zones
await fb2k.invoke('tray.clearMenuItems');

tray.create ​

Creates the tray icon. Call this before relying on tray visibility, callbacks, or menu operations.

ParameterTypeRequiredDescription
iconstringNoRaw Base64-encoded .ico file bytes without data: or base64: prefixes; empty, invalid, or omitted falls back to the foobar2000 main icon.
tooltipstringNoHover text. Default foobar2000.

Returns: {"error":"...","success":true}

js
await fb2k.invoke('tray.create', { tooltip: 'foobar2000' });

tray.destroy ​

Removes the tray icon.

No parameters.

Returns: {"success":true}

js
const result = await fb2k.invoke('tray.destroy');

tray.getMenuItems ​

Returns the current tray menu rows, including any declared playbackAction.

No parameters.

Returns: {"items":"...","success":true}

js
const result = await fb2k.invoke('tray.getMenuItems');

tray.isVisible ​

Reports whether the tray icon is currently shown.

No parameters.

Returns: {"success":true,"visible":"..."}

js
const result = await fb2k.invoke('tray.isVisible');

tray.removeMenuItems ​

Removes specific rows by id.

ParameterTypeRequiredDescription
idsarrayYesIds to remove. A missing or non-array value fails with ids array required.

Returns: {"error":"...","removed":"...","success":true}

removed reports how many rows were actually removed, which is not necessarily the number of ids passed.

js
const { removed } = await fb2k.invoke('tray.removeMenuItems', { ids: ['rescan'] });

tray.setCloseToTray ​

Makes closing the window hide it to the tray instead of quitting.

ParameterTypeRequiredDescription
enabledbooleanNoDefault false.

Returns: {"success":true}

js
await fb2k.invoke('tray.setCloseToTray', { enabled: true });

tray.setContextMenu ​

Replaces the whole tray menu definition.

ParameterTypeRequiredDescription
itemsarrayYesMenu rows. A missing or non-array value fails with items array required.
configobjectNoMenu-wide options such as showPlaybackControls, showSystemItems, and render.

items[].icon is a reserved compatibility field and is not rendered by either the native or WebView menu backend. For WebView-rendered item icons, use items[].iconSvg; the native backend is text-only.

Returns: {"error":"...","success":true}

js
await fb2k.invoke('tray.setContextMenu', {
    items: [
        { id: 'rescan', label: 'Rescan library' },
        { type: 'separator' },
        { id: 'settings', label: 'Settings', enabled: false },
    ],
    config: { showSystemItems: true },
});

tray.setIcon ​

Replaces the tray icon image.

ParameterTypeRequiredDescription
iconstringNoRaw Base64-encoded .ico file bytes without data: or base64: prefixes; empty, invalid, or omitted falls back to the foobar2000 main icon.

Returns: {"success":true}

js
// icoBase64: raw Base64-encoded .ico file bytes
await fb2k.invoke('tray.setIcon', { icon: icoBase64 });

tray.setMenuItemState ​

Toggles the checked or enabled state of one existing row.

ParameterTypeRequiredDescription
idstringYesId of the row to update.
checkedbooleanNoNew checked state.
enabledbooleanNoNew enabled state.

Returns: {"error":"...","found":"...","success":true}

An empty or missing id fails with id required, and omitting both checked and enabled fails with at least one of checked/enabled required. found reports whether a row with that id existed.

js
await fb2k.invoke('tray.setMenuItemState', { id: 'settings', enabled: true });

tray.setMinimizeToTray ​

Makes minimizing the window hide it to the tray.

ParameterTypeRequiredDescription
enabledbooleanNoDefault false.

Returns: {"success":true}

js
await fb2k.invoke('tray.setMinimizeToTray', { enabled: true });

tray.setTooltip ​

Updates the tray icon's hover text.

ParameterTypeRequiredDescription
tooltipstringNoHover text. Defaults to an empty string, which clears it.

Returns: {"success":true}

js
await fb2k.invoke('tray.setTooltip', { tooltip: 'Artist - Title' });

tray.showBalloon ​

Shows a balloon notification from the tray icon.

ParameterTypeRequiredDescription
titlestringNoNotification title. Defaults to an empty string.
messagestringNoNotification body. Defaults to an empty string.
iconstringNoOne of info, warning, error. Defaults to info, which is also used for any other value.

Returns: {"success":true}

js
await fb2k.invoke('tray.showBalloon', { title: 'Now Playing', message: 'Artist - Title' });

Contract supplements ​

The sections below close public-contract findings from the strict parameter audit without replacing existing explanations.

Contract supplement: taskbar.setProgress ​

ParameterTypeRequiredDefaultDescription
statestringNononeOne of none, indeterminate, normal, error, paused; any other value behaves as none.
valuenumberNo—Applied only when it is a number between 0 and 1 inclusive; otherwise the fill is left unchanged.

Return fields ​

FieldTypeOptional
successbooleanNo
panelModebooleanNo

success reflects whether the taskbar accepted the change, so it can be false even for valid parameters when the COM integration is not yet initialized. In panel mode the call returns { success: false, panelMode: true }.

js
// indeterminate ignores value
await fb2k.invoke('taskbar.setProgress', { state: 'indeterminate' });

Contract supplement: items[].playbackAction ​

playbackAction declares a native playback action executed by the plugin instead of the page. It accepts one of 'play-pause' | 'previous' | 'next' | 'stop' and is valid only on a type: 'normal' leaf.

AspectBehavior
ExecutionTranslated at composition time to the matching built-in command and run natively by the plugin.
Background reliabilityWorks while the window is minimized, hidden to tray, or the session is locked — states where the page is deep-suspended.
EventA declared item does not fire tray:menuItemClicked; reflect button state from playback:* events.
AppearanceThe caller keeps full control of label / icon / id; only routing changes.
ValidationFail-loud: an unknown token, or a declaration on a separator / submenu / rich control, rejects the whole setContextMenu / appendMenuItems call with INVALID_PARAMS.
'exit' / 'show-main-window'Not accepted — the system actions stay the reserved _sys_exit / _sys_show items.
ScopeTray menus only; no effect on menu.show.
Round-tripgetMenuItems() echoes the declared playbackAction.

Without this field, a user item that forwards tray:menuItemClicked to playback.* depends on the main WebView's JavaScript and will not run while the page is deep-suspended (minimize / tray / lock). Use playbackAction (or the built-in showPlaybackControls items) for background-reliable tray playback control. This mirrors the declarative native action pattern of Electron MenuItem.role and Tauri PredefinedMenuItem.

js
// Custom appearance + background-reliable native playback:
await fb2k.invoke('tray.setContextMenu', {
    items: [
        { id: 'prev', label: '⏮', playbackAction: 'previous' },
        { id: 'pp', label: '⏯', playbackAction: 'play-pause' },
        { id: 'next', label: '⏭', playbackAction: 'next' },
    ],
    config: { showPlaybackControls: false, render: 'webview' },
});