ldtray
Cross-platform tray icons for Rust that are never linked against any GUI or platform library at compile time.
Every platform toolkit — libdbus on Linux, shell32/user32 on Windows,
AppKit/objc on macOS — is resolved at runtime through
libloading. The result: one daemon binary runs
everywhere. On a headless server the only failure is a clean Err from
Tray::new ("the tray library could not be loaded") — never a link error, never
a crash. Ignore the error and your program keeps running without a tray.
Features
- Tray icon from raw RGBA pixels
- Click triggers: left / right / middle / double click
- Context menu with buttons, checkboxes, separators, and submenus
- Desktop notifications
- Update icon, tooltip, and menu live from any thread via a
Send + Synchandle - Blocking
run()(main-thread-correct, works on macOS) or backgroundspawn()(Linux/Windows)
Status
| Platform | Mechanism | State |
|---|---|---|
| Linux | StatusNotifierItem + dbusmenu over D-Bus | ✅ icon, triggers, menu, notifications |
| Windows | Shell_NotifyIcon + hidden window |
planned |
| macOS | NSStatusItem via the Obj-C runtime |
planned |
Usage
use ;
let icon = from_rgba?;
let menu = new
.item
.item
.item;
let tray = match new ;
let handle = tray.handle;
tray.run?;
Run the bundled example:
Design
The whole crate compiles with a single non-platform dependency (libloading).
Platform symbols are hand-bound FFI declarations resolved from a dlopen'd
library the first time a Tray is created. See src/platform/ for the
per-OS backends and docs/source comments for the wire-level details.
License
MIT © Karpelès Lab Inc.