Lightweight desktop widgets for Ubuntu GNOME, written in Rust.
zDesk is a Conky-inspired desktop widget application that displays a digital clock, weekday indicator, personalized greeting, and circular CPU, temperature, and RAM indicators. The widget runs as a small native Rust process using X11/XWayland. A separate GTK4/libadwaita application provides graphical settings.
Current version: v0.1.3
Author: Azis Lamayuda
License: MIT
Compatibility: Developed and tested on Ubuntu GNOME with a Wayland session and XWayland. Other desktop environments and compositors have not been verified. zDesk requires a compatible 32-bit ARGB X11 visual and related X11 extensions.
- Digital clock with customizable 24/12-hour format, font, size, color, and position.
- Five theme presets (Default, Minimal Dark, Nord, Cyberpunk, Custom), applied to all widget colors without changing saved custom colors.
- Weekday labels with an active-day indicator.
- Time-dependent greetings with customizable text, name, suffix, start hours, and live Settings preview.
- Circular CPU usage, CPU temperature, and RAM usage widgets.
- Transparent, click-through desktop windows.
- Support for multiple monitors via XRandR, using one widget process.
- Lightweight drawing without loading GTK into the widget process.
- Separate zDesk Settings GUI built with GTK4 and libadwaita.
- TOML configuration with validation and Save & Apply.
- Optional autostart that waits for GNOME to finish logging in (usually a few seconds), with a crash-recovery guard.
- Settings controls for autostart, start/stop/restart, recovery-guard reset, and status/diagnostics (versions, service state, RAM, config check, journal).
- GitHub Actions workflow for automatic/manual draft-only releases on version bumps.
- Linux desktop running Ubuntu GNOME with XWayland available.
- Rust and Cargo to build the project.
- For the Settings GUI:
pkg-config, GTK4 development files, and libadwaita 1.9 or newer development files. - TTF/OTF fonts referenced by the configuration file.
On a compatible Ubuntu version, install the system build dependencies with:
sudo apt update
sudo apt install build-essential pkg-config libgtk-4-dev libadwaita-1-devInstall or update Rust/Cargo separately if they are not already available. Verify the installed development libraries with:
rustc --version
cargo --version
pkg-config --modversion gtk4
pkg-config --modversion libadwaita-1Fonts are not bundled. The example configuration references Monoton, Bebas Neue, Roboto, and DejaVu Sans Mono font files. Install the necessary fonts or edit their paths in config/default.toml / ~/.config/zdesk/config.toml before starting zDesk. The example greeting name should also be personalized.
From the root of the cloned zDesk repository:
# Build and install the widget, configuration and systemd user units
bash scripts/install.sh
# Build and install the separate Settings application and GNOME launcher
bash scripts/install-settings.shDo not use sudo with these installer scripts. They install into the current user's home directory:
| Installed component | Location |
|---|---|
| Widget binary | ~/.local/bin/zdesk |
| Settings binary | ~/.local/bin/zdesk-settings |
| User configuration | ~/.config/zdesk/config.toml |
| Example configuration | ~/.config/zdesk/example.toml |
| Service | ~/.config/systemd/user/zdesk.service |
| Timer | ~/.config/systemd/user/zdesk.timer |
| Startup guard | ~/.local/lib/zdesk/login-guard.sh |
| GNOME Settings launcher | ~/.local/share/applications/id.lamayuda.zDesk.Settings.desktop |
The widget installer preserves an existing edited configuration and disables zDesk autostart during installation. It does not remove an older DeskLamayuda installation automatically. Check for older user services before enabling zDesk's timer so that two versions do not run simultaneously.
zdesk --version
zdesk --check-config ~/.config/zdesk/config.tomlExpected version: zDesk 0.1.3. Configuration validation also checks referenced font files and does not open a desktop window.
When first installing or migrating, keep automatic startup disabled and test the service after the GNOME desktop is fully loaded:
systemctl --user start zdesk.service
systemctl --user --no-pager status zdesk.serviceTo stop the widget:
systemctl --user stop zdesk.serviceTo run a build directly without installing it, first ensure ~/.config/zdesk/config.toml exists, then run:
cargo build --release --locked
./target/release/zdeskzdesk does not accept a positional configuration path. Use --check-config /path/to/file.toml to validate a particular file.
Open zDesk Settings from the GNOME application menu, or run:
zdesk-settingsThe editor provides settings for the clock, weekday labels, greeting, positions, ring layout, colors, and sensor refresh interval. v0.1.3 additionally offers theme selection and live theme color preview, per-time greeting messages and preview, editable clock/weekday/greeting/rings font paths, active/inactive weekday dot colors, individual CPU/TEMP/RAM ring colors, and ring background opacity using #RRGGBBAA.
Startup & Service (top of the window):
- Start automatically after login enables or disables the systemd user timer only. Turning it on never starts the widget immediately; turning it off cancels a pending start but leaves a running widget alone.
zdesk.serviceis never enabled directly. - Start / Stop / Restart control the widget now.
- Recovery guard shows whether autostart is paused after an unclean start, with Reset to allow the next autostart.
Status & Diagnostics shows the widget and Settings versions (and warns if they differ), service state, PID, RAM, last result and restart count, whether the installed widget accepts your configuration, and the last journal lines of this boot. The copy button puts a complete report on the clipboard. Everything runs as your user, without sudo. Click Save & Apply to validate and save edits. If the widget service is active, Settings requests a service restart to apply the updated configuration. The settings file's unrelated values and comments are preserved, and a backup is created when saving changes.
The Settings application runs only when opened; GTK4/libadwaita is not loaded by the widget itself. More advanced options can be changed directly in the TOML file. Existing v0.1.2 configuration files without [theme] are valid: Default means the original v0.1.2 colors. Preset themes change rendered colors only, keeping the configured colors intact; select Custom to view/edit those colors again. Some fonts may lack a custom greeting character; --check-config checks supported glyphs before applying.
For the precise theme mapping and safe draft workflow see docs/v0.1.3-CUSTOMIZATION-AND-RELEASE.md.
Important: An earlier iteration of this project was associated with a GNOME/XWayland login-loop incident. Delayed startup and the guard reduce the risk of repeated automatic launches, but cannot guarantee that the compositor will never fail.
The installed zdesk.service does not restart automatically (Restart=no). Since v0.1.3 the startup sequence is:
zdesk.timerfires 2 seconds after the graphical session starts.login-guard.sh checkskips the start if an earlier attempt did not finish cleanly.login-guard.sh wait-readywaits until GNOME reports that the session is running (org.gnome.SessionManager.IsSessionRunning) andDISPLAY,WAYLAND_DISPLAYandXAUTHORITYare available, then waits 3 more seconds. Without GNOME's session manager it falls back to the old 30-second delay. If GNOME is not ready within 90 seconds, the start is skipped.login-guard.sh armwrites the recovery marker; the widget then waits for GNOME's window manager on XWayland before showing any window, and clears the marker after 60 seconds of stable running.
Earlier versions used a fixed 30-second delay because starting an X11 client while GNOME was still starting could hang the login. The readiness check targets that cause directly instead of guessing a time. The waits can be tuned with a drop-in (systemctl --user edit zdesk.service), for example:
[Service]
Environment=ZDESK_SETTLE_DELAY=10
Environment=ZDESK_READY_TIMEOUT=120To go back to the v0.1.2 behavior (fixed 30-second delay), add a timer drop-in with systemctl --user edit zdesk.timer:
[Timer]
OnActiveSec=
OnActiveSec=30sAs before, the installer disables autostart during an upgrade; verify a full logout/login cycle before enabling it again.
Only after successful manual tests and a normal logout/login test, enable autostart:
systemctl --user enable zdesk.timerThe timer will be activated by the graphical user session; it is not necessary to enable zdesk.service directly. To disable autostart and stop the widget:
systemctl --user disable --now zdesk.timer
systemctl --user stop zdesk.serviceIf a future login is affected, try Ctrl + Alt + F3 to access a text console (TTY), sign in, then disable the user timer:
systemctl --user disable --now zdesk.timer
systemctl --user stop zdesk.serviceIf the user systemd manager is unavailable from TTY, remove the autostart symlink and try logging in again:
rm -f ~/.config/systemd/user/graphical-session.target.wants/zdesk.timerThese commands only target zDesk's autostart and do not modify GNOME Shell or GDM. A different GNOME failure may require separate diagnosis.
If a guarded startup was skipped, inspect the logs and reset the marker only after the desktop is stable:
journalctl --user -u zdesk.service -n 50 --no-pager
~/.local/lib/zdesk/login-guard.sh reset# Desktop widget
cargo fmt --all -- --check
cargo test --locked
cargo build --release --locked
# Separate Settings app
cargo fmt --manifest-path settings/Cargo.toml --all -- --check
cargo test --manifest-path settings/Cargo.toml --locked
cargo build --manifest-path settings/Cargo.toml --release --lockedFor a one-minute resource measurement while the widget is running:
bash scripts/benchmark.sh 60zDesk v0.1.2 and newer reuse sensor text buffers and skip regenerating identical ring value text; v0.1.3 also skips repainting the ring window when neither the number nor the visible arc changed. Sensor arcs and readings still refresh according to rings.refresh_ms. These changes target allocation overhead; lower RSS or CPU usage is not guaranteed and should be measured on the same desktop before and after upgrading.
The benchmark script reads CPU and memory statistics from /proc; it can also report Conky statistics when Conky is running. Results depend on the machine, monitor arrangement, and workload. One initial Ubuntu desktop test of zDesk v0.1.0 measured approximately 4.8 MiB RSS and 0.1–0.2% CPU in short samples; this is not a long-term performance guarantee.
bash scripts/compare-release-size.shThis compiles three separate release targets for opt-level = 3, s and z. v0.1.3 ships opt-level = "s" after comparing size, memory, CPU and rendering, and no longer links serde, toml or tiny-skia into the widget (they remain dev-dependencies used by tests to cross-check zDesk's own TOML reader and rasterizer).
After pushing a version change in both Cargo manifests to main using GitHub Desktop, the zDesk Draft Release workflow can run automatically. Or open Actions → zDesk Draft Release → Run workflow. It tests both Rust applications and creates an unpublished draft vX.Y.Z with notes from CHANGELOG.md. It never publishes automatically. GitHub Actions uses Ubuntu 26.04 to meet libadwaita >=1.9. A version bump without successful tests creates no draft. See docs/v0.1.3-CUSTOMIZATION-AND-RELEASE.md.
| Symptom | What to check |
|---|---|
| Missing font / invalid config | Run zdesk --check-config ~/.config/zdesk/config.toml and correct the referenced font paths. |
| Widget does not start through systemd | Check systemctl --user status zdesk.service and journalctl --user -u zdesk.service -n 50 --no-pager. |
| XWayland environment unavailable | Compare DISPLAY, WAYLAND_DISPLAY, and XAUTHORITY with systemctl --user show-environment. |
| Window placement differs | Inspect xrandr --listmonitors; GNOME/Mutter ultimately controls XWayland window placement. |
| Settings changes are not visible | Check whether the service is active, then use Save & Apply or restart it manually. |
| Startup guard skips launch | Review the journal; reset the guard only after GNOME is stable (Settings → Recovery guard → Reset). |
| Autostart skipped: "desktop not ready" | GNOME did not report a running session within 90 s; check journalctl --user -b -u zdesk.service and raise ZDESK_READY_TIMEOUT if your login is slow. |
zDesk/
├── Cargo.toml
├── Cargo.lock
├── README.md
├── LICENSE
├── CHANGELOG.md
├── config/
│ ├── default.toml
│ └── v0.1.toml
├── src/ # Native Rust desktop widget
├── settings/ # GTK4/libadwaita Settings app (separate Cargo package)
├── scripts/ # Installers, login guard, benchmark
├── systemd/ # User service and delayed timer
└── docs/ # Historical development notes
- Designed primarily for Ubuntu GNOME with XWayland; other environments are not verified.
- Configuration changes require a service restart; there is no live config reload.
- Advanced configuration options are edited directly in TOML.
- GNOME/Mutter controls final placement of XWayland desktop-type windows.
zDesk is released under the MIT License. See LICENSE. Third-party Rust crates, GTK libraries, and font files remain subject to their respective licenses.
Copyright © 2026 Azis Lamayuda.