# System tray icons via D-Bus

**URL:** <https://ziggit.dev/t/system-tray-icons-via-d-bus/12750>\
**Category:** Showcase\
**Tags:** c, build-system\
**Created:** [October 30, 2025, 2:41am UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750 "2025-10-30T02:41:55Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [October 30, 2025, 2:41am UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/1 "2025-10-30T02:41:55Z")

</div>

I was trying to implement a basic system tray icon using some gui kit but ended up making [this](https://github.com/charlesrocket/libstray) c lib. Turned out this is a pretty challenging (?) topic. GTK4 dropped support, 3rd party libs are deprecated or require GTK3 (the ones I thought I could get to work).

So this is a pure c dbus system tray handler wrapped in Zig. No Glib, no GTK, no QT. Dynamic icons/titles work, as well as simple menus + callbacks. Pretty minimal, I am trying to expand.

Testing on FreeBSD/Hyprland/eww.

![stray1](https://ziggit.dev/uploads/default/original/2X/4/44e6148b5cc937a2de384a4a95c9e65c78463018.png)

 ![stray2](https://ziggit.dev/uploads/default/original/2X/1/12e83470f833d561a1f152ea3e66bfe1eebeed65.png)

demo:

```shell
 zig build run

```

> <https://github.com/charlesrocket/libstray/blob/48277e665373ffff34ac2fdddc845c087e79c2f8/example/demo.zig>

Not sure if this works on macos, there is dbus brew tho. Need to figure out if I can test it on BSD.

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [October 30, 2025, 3:05am UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/2 "2025-10-30T03:05:00Z")

</div>

There is also [GitHub - AyatanaIndicators/libayatana-appindicator-glib: Ayatana Application Indicators Shared Library (GLib-2.0 reimplementation, 100% GTK-free, 100% dbusmenu-free)](https://github.com/AyatanaIndicators/libayatana-appindicator-glib) but its GPL and broken [README lies about being implementation of StatusNotifierItem · Issue #89 · AyatanaIndicators/libayatana-appindicator-glib · GitHub](https://github.com/AyatanaIndicators/libayatana-appindicator-glib/issues/89).

---

<div class="post-metadata">

**Author:** ![Southporter](https://ziggit.dev/user_avatar/ziggit.dev/southporter/32/2500_2.png) [@Southporter](https://ziggit.dev/u/Southporter)\
**Post date:** [October 30, 2025, 3:08pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/3 "2025-10-30T15:08:04Z")

</div>

I’ve been looking to do this exact thing for my little break notification app. I was getting nowhere with dbus docs, so this will be a great help. Thanks.

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [October 30, 2025, 3:16pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/4 "2025-10-30T15:16:25Z")

</div>

No worries! I hope it works for you! I am pushing a fix for linux in a few.

Yea the docs are not great, but I guess the level is too low, so there are not many consumers.

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [October 30, 2025, 4:35pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/5 "2025-10-30T16:35:20Z")

</div>

zig 0.15-ready

## 0.1.0

### Bug Fixes

- Update `callconv()`
- Update `sleep()`

### Documentation

- Add README.md
- Update features
- Fix `TrayIcon` comment
- Update comments

### Features

- Add menu support
- Add demo app

### Miscellaneous tasks

- Add LICENSE
- Set indentations
- Add gitignore
- Ignore `zig-out`

### Operations

- Add demo test
- Install dependencies

### Refactor

- Move declarations

### Styling

- Change alignment
- Fix formatting
- Break open brackets

### Build

- Add `docs` step
- Fix library links

> **[Release 0.1.0 · charlesrocket/libstray](https://github.com/charlesrocket/libstray/releases/tag/0.1.0)**
>
> Bug Fixes
> 
> Update callconv()
> Update sleep()
> 
> Documentation
> 
> Add README.md
> Update features
> Fix TrayIcon comment
> Update comments
> 
> Features
> 
> Add menu support
> Add demo app
> 
> Miscellaneous tasks
> 
> Add LIC...

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [November 3, 2025, 3:42pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/6 "2025-11-03T15:42:43Z")

</div>

## 0.1.1

### Bug Fixes

- Drop `c_allocator`
- Resolve leaking items
- Fix array list
- Update `onQuit`

### Documentation

- Update description
- Adjust description
- Reformat comments

### Miscellaneous tasks

- Add CI badge

### Operations

- Add test job

### Testing

- Add basic app

### Build

- Bump MSZV to 0.15.2

> **[Release 0.1.1 · charlesrocket/libstray](https://github.com/charlesrocket/libstray/releases/tag/0.1.1)**
>
> Bug Fixes
> 
> Drop c\_allocator
> Resolve leaking items
> Fix array list
> Update onQuit
> 
> Documentation
> 
> Update description
> Adjust description
> Reformat comments
> 
> Miscellaneous tasks
> 
> Add CI badge
> 
> Operations...

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [November 10, 2025, 10:59pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/7 "2025-11-10T22:59:00Z")

</div>

Fixed some signaling bugs and added custom pixmaps, radio/check items, and tooltips. Almost done! Need to play with item icons and submenus, and it will be finished.

## 0.2.0

### Bug Fixes

- Drop redundant error print
- Improve watcher error
- Resolve leaks
- `icon` destroys the menu
- Set proper service name
- Resolve dynamic updates
- Clean up pixmap infra

### Documentation

- Update description
- Fix gnome description

### Features

- [**breaking**] Add allow item control
- [**breaking**] Add pixmap support
- Add tooltips
- Add radio item support

### Styling

- Fix `stray_register()`
- Update format

### Testing

- Add disabled item
- Add title
- Update pixmaps
- Add checked item

> **[Release 0.2.0 · charlesrocket/libstray](https://github.com/charlesrocket/libstray/releases/tag/0.2.0)**
>
> Bug Fixes
> 
> Drop redundant error print
> Improve watcher error
> Resolve leaks
> icon destroys the menu
> Set proper service name
> Resolve dynamic updates
> Clean up pixmap infra
> 
> Documentation
> 
> Update descrip...

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [November 11, 2025, 4:01pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/8 "2025-11-11T16:01:43Z")

</div>

> <https://github.com/charlesrocket/libstray/pull/9>
>
> Closes #5

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [November 11, 2025, 10:30pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/9 "2025-11-11T22:30:19Z")

</div>

everything works smoothly with eww and waybar, no warnings in dbus. ~~but kde shows main menu in the submenu aah. this is fun.~~ fixed kde menus

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [November 12, 2025, 4:29am UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/10 "2025-11-12T04:29:07Z")

</div>

> <https://github.com/charlesrocket/libstray/pull/10>
>
> Menu icons don't get custom pixmaps, D-Bus protocol requires PNG format. It is m…ore efficient to just install PNG icons and use them like named icons.

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [March 21, 2026, 8:22pm UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/11 "2026-03-21T20:22:42Z")

</div>

## 0.4.0

### Bug Fixes

- Update app layout
- Improve submenu handling
- Add test item
- Change label
- Check all strings in `stray_create`
- Improve menu checks
- Handle multiple instances
- Improve scroll handling
- Ensure `NewStatus` is flushed
- Check message type in `register_with_watcher()`
- Clean up `emit_properties_changed()`
- Remove redundant signals from `stray_set_icon_pixmap()`
- Use global menu id root
- Drop redundant `WindowId`
- Check `create_menu_item()`
- Safeguard filter/match rule
- Check pixmap size
- Update `setIconPixmap()`
- Correct checked item

### Documentation

- Update `fd()` description

### Features

- Add file descriptor
- [**breaking**] Track registrations
- [**breaking**] Add x/y callback coordinates
- Add `onScroll`
- Add `window_id`
- Add `onRemovePixmap()`

### Performance

- Drop `usleep()`

### Refactor

- Move `*RadioGroup`
- Improve `stray_destroy()` logic
- Consistent user data fields
- Drop redundant zeroing loop
- Drop redundant `emit_properties_changed()`

### Styling

- Fix formatting
- Disable `AlignAfterOpenBracket`
- Align open brackets
- Align operands

### Testing

- Add callbacks

> **[Release 0.4.0 · charlesrocket/libstray](https://github.com/charlesrocket/libstray/releases/tag/0.4.0)**
>
> Bug Fixes
> 
> Update app layout
> Improve submenu handling
> Add test item
> Change label
> Check all strings in stray\_create
> Improve menu checks
> Handle multiple instances
> Improve scroll handling
> Ensure NewSt...

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [May 21, 2026, 1:21am UTC](https://ziggit.dev/t/system-tray-icons-via-d-bus/12750/12 "2026-05-21T01:21:32Z")

</div>

## 0.4.1

### Bug Fixes

- Empty payload clears pixmap
- Update `main()`
- Update test runner

### Operations

- Bump actions/deploy-pages from 4.0.5 to 5.0.0
- Bump actions/configure-pages from 5.0.0 to 6.0.0
- Bump actions/upload-pages-artifact from 4.0.0 to 5.0.0
- Bump zig to 0.16

### Refactor

- Add `emit_signal_string()`
- Drop redundant ternary
- Add `status_to_string()`
- Recursive `find_menu_item()`
- Add `notify_item_changed()`

### Styling

- Improve alignments

### Build

- Drop `clean`
- Bump MSZV to 0.16

> **[Release 0.4.1 · charlesrocket/libstray](https://github.com/charlesrocket/libstray/releases/tag/0.4.1)**
>
> Bug Fixes
> 
> Empty payload clears pixmap
> Update main()
> Update test runner
> 
> Operations
> 
> Bump actions/deploy-pages from 4.0.5 to 5.0.0
> Bump actions/configure-pages from 5.0.0 to 6.0.0
> Bump actions/uplo...
