sevaht_gui.tray

Cross-platform tray-icon abstraction.

The application talks to a single TrayIcon interface; create_tray_icon() hides which backend implements it:

  • Windows -> pystray.

  • Linux -> StatusNotifierItem when a usable SNI host is present (KDE/GNOME, Wayland, or fluxbox with snixembed), otherwise the self-contained XEmbed backend. The Linux wrapper also transparently falls back from SNI to XEmbed if SNI registration fails at startup.

The tray exposes a deliberately small, two-action feature model:

  • on_activate – the default action (left-click, and the default menu item on backends that have a menu).

  • on_quit – the quit action.

Backends that can show a menu (pystray, SNI) offer both actions as menu items on right-click. The XEmbed backend cannot show a menu, so right-click invokes on_quit directly. The icon and title/tooltip can be updated at any time, and desktop notifications can be raised via TrayIcon.notify().

exception sevaht_gui.tray.SNIRegistrationError[source]

Bases: RuntimeError

Raised when the SNI backend cannot register with a watcher at startup.

Signals the Linux wrapper to fall back to the XEmbed backend, which needs no StatusNotifierItem host. Handled internally by _LinuxTrayIcon.

sevaht_gui.tray.tray_available() bool[source]

Return True if a system tray a tray icon can dock into is present.

Lets callers degrade gracefully (run without a tray icon) when no tray host exists – e.g. a bare X11 session with no panel. On Windows the notification area is assumed always present.

sevaht_gui.tray.as_renderer(icon: IconSource) IconRenderer[source]

Normalize any IconSource to an IconRenderer.

A renderer is returned unchanged. A static source (PIL image or file path) is loaded once and wrapped in a renderer that returns it scaled to the requested size, so a fixed image works anywhere a renderer is expected.

class sevaht_gui.tray.TrayIcon(*args, **kwargs)[source]

Bases: Protocol

The tray-icon surface the application relies on, regardless of backend.

set_icon(icon: IconSource) None[source]

Replace the icon with any IconSource (static or renderer).

notify(title: str, message: str, *, icon: str | None = None) None[source]

Show a desktop notification.

icon (a freedesktop icon name) is used where supported (Linux); Windows shows the tray icon’s own image.

run(setup: SetupCallback | None = None) None[source]

Run the tray event loop, calling setup once it is ready.

stop() None[source]

Stop the tray event loop.

sevaht_gui.tray.create_tray_icon(name: str, title: str, icon: IconSource, *, on_activate: Callable[[], None] | None = None, on_quit: Callable[[], None] | None = None, activate_label: str = 'Open', quit_label: str = 'Quit') TrayIcon[source]

Create the platform-appropriate tray icon behind TrayIcon.

name is a machine-friendly identifier (used for the SNI item id and the XEmbed window class); title is the human-readable tooltip. icon is any IconSource – a prepared PIL image, an image file path, or a renderer; swap it later with TrayIcon.set_icon() to reflect state. on_activate is the default action (left-click / default menu item) and on_quit is the quit action; either may be omitted. activate_label / quit_label are the menu labels used by backends that show a menu.