desktop_tray 2026.4.4
desktop_tray: ^2026.4.4 copied to clipboard
A Flutter plugin for managing system tray icons and menus on desktop platforms (Windows, macOS, Linux).
desktop_tray #
A lightweight Flutter plugin for managing system tray icons and context menus on desktop platforms (Windows, macOS, Linux).
Built with zero third-party Dart dependencies β only native platform APIs:
| Platform | Backend |
|---|---|
| Linux | libayatana-appindicator (or legacy libappindicator) |
| macOS | NSStatusBar + NSMenu |
| Windows | Win32 Shell_NotifyIcon + TrackPopupMenu |
π¨π³ δΈζζζ‘£
Features #
- πΌοΈ Set a tray icon from Flutter asset paths (
.png/.ico) - π¬ Set a hover tooltip (supported on all platforms)
- π Build context menus with normal items, separators, checkboxes, and nested submenus
- π±οΈ Receive left-click, right-click, and menu-item-click callbacks via a listener mixin
- π§© Unique auto-incremented item IDs β no external ID generators needed
Getting Started #
Installation #
Add the package as a path dependency in your app's pubspec.yaml:
dependencies:
desktop_tray:
path: packages/desktop_tray
Linux System Dependencies #
The Linux implementation requires libayatana-appindicator3 (preferred) or libappindicator3:
# Ubuntu / Debian
sudo apt install libayatana-appindicator3-dev
# Fedora
sudo dnf install libayatana-appindicator-gtk3-devel
# Arch
sudo pacman -S libayatana-appindicator
Usage #
Basic Setup #
import 'package:desktop_tray/desktop_tray.dart';
// 1. Set the tray icon
await desktopTray.setIcon('assets/logo/logo.png');
// 2. Set a tooltip
await desktopTray.setToolTip('My App');
// 3. Build a context menu
final menu = TrayMenu(items: [
TrayMenuItem(key: 'show', label: 'Show Window'),
TrayMenuItem.separator(),
TrayMenuItem(key: 'exit', label: 'Exit'),
]);
await desktopTray.setContextMenu(menu);
Listening to Events #
Implement DesktopTrayListener and register it:
class MyTrayHandler with DesktopTrayListener {
MyTrayHandler() {
desktopTray.addListener(this);
}
@override
void onTrayIconMouseDown() {
// Left-click on tray icon
}
@override
void onTrayMenuItemClick(TrayMenuItem item) {
switch (item.key) {
case 'show':
// show window
break;
case 'exit':
// exit app
break;
}
}
}
Menu Item Types #
// Normal item
TrayMenuItem(key: 'action', label: 'Do Something')
// Separator
TrayMenuItem.separator()
// Checkbox
TrayMenuItem.checkbox(key: 'mute', label: 'Mute', checked: true)
// Submenu
TrayMenuItem.submenu(
key: 'more',
label: 'More Options',
children: [
TrayMenuItem(key: 'option_a', label: 'Option A'),
TrayMenuItem(key: 'option_b', label: 'Option B'),
],
)
Cleanup #
desktopTray.removeListener(this);
await desktopTray.destroy();
API Reference #
DesktopTray (singleton via desktopTray) #
| Method | Description |
|---|---|
setIcon(String assetPath) |
Set tray icon from a Flutter asset path |
setToolTip(String toolTip) |
Set hover tooltip text (no-op on Linux) |
setContextMenu(TrayMenu menu) |
Replace the right-click context menu |
popUpContextMenu() |
Programmatically open the context menu (no-op on Linux) |
destroy() |
Remove the tray icon and release native resources |
addListener(DesktopTrayListener) |
Register an event listener |
removeListener(DesktopTrayListener) |
Unregister an event listener |
DesktopTrayListener (mixin) #
| Callback | Trigger |
|---|---|
onTrayIconMouseDown() |
Left mouse button pressed on tray icon |
onTrayIconMouseUp() |
Left mouse button released on tray icon |
onTrayIconRightMouseDown() |
Right mouse button pressed on tray icon |
onTrayIconRightMouseUp() |
Right mouse button released on tray icon |
onTrayMenuItemClick(TrayMenuItem) |
A context menu item was clicked |
Platform Notes #
- Linux: AppIndicator always shows the context menu on left-click.
popUpContextMenu()is a no-op. Tooltip is not supported by the AppIndicator API. The deprecation warning from newer versions of libayatana-appindicator is silently suppressed. - macOS: Icon data is sent as base64 to the native layer for
NSImageconstruction. - Windows: Expects
.icoformat icons for the best display quality.
License #
See LICENSE.