Containerpak / Containerpak/cpak

[Feature] Support legacy XEmbed system tray icons on Wayland via SNI bridge

Open
#58 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
191
Forks
3
Avg merge
27m
Merged PRs (30d)
16

Description

Problem

Apps using Qt's QSystemTrayIcon / GTK StatusIcon rely on the XEmbed
protocol (_NET_SYSTEM_TRAY_S0). Under cpak's nested displayX11
(Xwayland/Xephyr), nothing claims that selection, so the tray icon
is created but never rendered anywhere — the app itself needs zero
changes, there's just no tray manager present in the nested display.

Example: fptn-client-gui (Qt), tray icon silently disappears when
packaged for a pure-Wayland session (Niri, Hyprland, Sway).

Proposed solution

Don't reimplement XEmbed↔SNI translation — tools like snixembed
already do exactly this (claim the tray selection, expose a
StatusNotifierItem on D-Bus, replay clicks back via XSendEvent).
This is the same pattern non-containerized Wayland users already
rely on today with unmodified Qt/GTK apps.

Concretely, when displayX11 is set and a new flag is enabled:

"override": {
  "displayX11": true,
  "trayProxy": "xembed"
}

cpak would:

  1. Fetch/verify a static snixembed-equivalent binary (same pattern
    as the slirp4netns bootstrap) and launch it inside the nested
    X session before the app starts.
  2. Widen the existing private desktop D-Bus proxy (currently used
    for org.freedesktop.appearance / notifications / openURI) to
    also forward org.kde.StatusNotifierItem and
    org.kde.StatusNotifierWatcher calls between the bridge and
    the host bus.

No pixmap capture or click-translation logic needs to be written —
the bridge already implements both directions; cpak only needs to
supervise its lifecycle and open the D-Bus interface allowlist.

Why this is low risk

Same components (Xwayland tray bridge → SNI → Wayland panel) are
already used unmodified outside containers. This is wiring, not
new protocol work.

Open question

Would you rather scope the D-Bus interface allowlist per-package
(declared permission) or make it a fixed part of trayProxy?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the existing displayX11 handling, the slirp4netns bootstrap, and the private desktop D-Bus proxy mentioned in the issue. Then determine how trayProxy configuration should control bridge startup and the StatusNotifierItem/Watcher allowlist. Done means the bridge is fetched, verified, supervised in the nested X session, and legacy tray icons are visible through the host Wayland panel.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, linux
Domain
desktop, operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.