HWDE is the native desktop environment for HackerOS, a Linux distribution aimed at daily use, gaming, cybersecurity work, development, and privacy-conscious users.
Version 0.1 (see CHANGELOG state below) - built on SolidJS +
Rust/Tauri v2 (shell) + Smithay (compositor).
HWDE-Project/
├── source-code/
│ ├── fronted/ SolidJS + TypeScript shell UI (Vite)
│ └── backend/
│ └── src-tauri/ Rust/Tauri v2 backend -> binary: starthwde
├── compositor/ Smithay 0.7 Wayland/XWayland compositor -> binary: comphwde
├── ipc/ Shared IPC protocol crate (package: hwde-ipc) used by both binaries
├── config/ .desktop / session / distro packaging files
├── images/ Source art (logo, default wallpaper) - see images/README.md
├── install.hl / remove.hl Standalone install/uninstall scripts (also used by `make install`)
├── .github/workflows/ CI: builds a .deb from source
├── Cargo.toml Cargo workspace
└── Makefile `make build`, `make shell`, `make compositor`, `make install`, ...
make build # everything, release mode
make shell # just starthwde (frontend + Tauri backend)
make compositor # just comphwde
make dev # run the shell windowed, no compositor (fastest inner loop)
sudo ./install.hl # install to /usr/bin, session file, default wallpaperRequirements: Rust >= 1.80 (via rustup), Node.js >= 20, the usual Tauri
v2 Linux deps (libwebkit2gtk-4.1-dev, libgtk-3-dev, librsvg2-dev, ...),
Wayland/compositor deps (libwayland-dev, libxkbcommon-dev,
libinput-dev, libgbm-dev, libseat-dev), and for full functionality at
runtime: NetworkManager (nmcli, Wi-Fi panel), bluez
(bluetoothctl, Bluetooth panel), pipewire/pulseaudio (pactl, volume
panel), and optionally xrandr (display panel, X11/nested only for now).
Rust/Wayland code in this repo is written carefully against real Smithay 0.7 APIs and cross-checked against Smithay's own reference compositor (
anvil), but could not becargo check-verified end-to-end in the sandboxed environment it was assembled in (too old a Rust toolchain to resolve current crates.io dependency trees). The SolidJS frontend was fully installed, type-checked (tsc --noEmit), and built (vite build) successfully at every step. Runcargo check --workspacefirst on a machine with Rust >= 1.80.
starthwde full graphical session - meant to be launched by
SDDM (see config/session/hwde.desktop) or from a
TTY. Spawns and supervises comphwde. Full window
management (focus/close/minimize/maximize for
*external* apps too) is live in this mode.
starthwde dev runs the shell as an ordinary windowed app. No
compositor is spawned, and by design external-app
window management is a no-op here (the taskbar
just shows in-shell windows).
starthwde app <name> launches a single HWDE app (e.g. `settings`,
`clipboard`, `about`, `emoji`) with no shell chrome.
They talk over a small NDJSON protocol on a Unix socket (ipc/, package
hwde-ipc). As of v0.1:
starthwdespawnscomphwdeand waits for it to become ready.launch_external_app->IpcRequest::LaunchApp: run an arbitrary binary as a Wayland/XWayland client of the session.list_all_windows/focus_window/close_window/minimize_window/maximize_window(Tauri commands) ->ListWindows/FocusWindow/CloseWindow/MinimizeWindow/MaximizeWindow(IPC): the SAME taskbar inBottomBar.tsxshows and controls both in-shell app windows and external ones - external windows are tracked compositor-side (ManagedWindowincompositor/src/state.rs) with stable numeric ids.- Session shutdown.
This is intentionally a bespoke, simple protocol rather than implementing
wlr-foreign-toplevel-management (the "standard" way other shells expose
window lists) - it gets HWDE's own shell the same practical result with far
less new surface area (no new wayland-client dependency inside
starthwde), at the cost of not being usable by other third-party
taskbars. Revisit if that ever matters.
Every Tauri command that did blocking work (nmcli, bluetoothctl,
pactl, image decoding, filesystem scans, sqlite) was a plain fn, which
Tauri v2 runs on the main thread - the same thread the webview itself
runs on. Opening the launcher or the Wi-Fi panel visibly froze the whole
shell until that work finished. Fixed by converting every such command to
async fn + async_util::blocking/blocking_res (spawn_blocking under
the hood). See source-code/backend/src-tauri/src/async_util.rs for the
full explanation. The frontend also now shows a spinner + status text
while these resources load instead of just looking stuck
(components/Spinner.tsx, wired into the launcher and the Wi-Fi/Bluetooth/
display panels).
~/.config/HWDE/settings.hk- small settings (theme, wallpaper, icon theme, launcher icon, language), using the realhk-parsercrate for the HackerOS.hkformat.~/.cache/HWDE/hwde.db- sqlite; currently just app launch-count stats (powers "most used" sorting in the launcher / Big Picture mode).~/.cache/HWDE/desktop-entries.json- cached, parsed.desktopscan results (seedesktop_entries.rs); refresh from Settings -> Aplikacje.
Both dynamically resolved and shipped to the webview as data: URLs
(no Tauri asset-protocol/CSP dependency):
- Wallpaper defaults to
/usr/share/wallpapers/HackerOS-Wallpapers/Wallpaper23.png(placeholder art inimages/wallpapers/), changeable from Settings. - App/launcher icons resolve through a simplified freedesktop Icon Theme
Specification lookup (
desktop_entries::resolve_icon), checking the configured theme (KDE Breeze included), thenhicolor/Adwaita, then/usr/share/pixmaps. SVG icons are passed through natively (no rasterization needed); raster icons go through the same small-PNG pipeline as wallpaper thumbnails. - The launcher button's own icon defaults to
/usr/share/HackerOS/ICONS/HackerOS.png, also user-configurable.
Merges HWDE's own built-in apps with every .desktop entry found under
~/.local/share/applications, XDG_DATA_DIRS, and common Flatpak/Snap
export paths - see desktop_entries.rs. Categories are a Plasma-inspired
set (Gry, Programowanie, Grafika, Internet, Multimedia, Biuro, Nauka,
Ustawienia, System, Narzędzia, Osobiste, Inne). "Ulubione" surfaces
built-ins plus the most-launched external apps (via the usage database).
Compositor:
- Still only the windowed (
winit) backend is wired intomain.compositor/src/backend_drm.rsnow has real session/udev-hotplug/ libinput code (ported from Smithay'sanvilreference compositor), but the atomic-KMS device/connector setup and vblank render loop are a precise, sourced outline rather than a mechanical port - that specific code is genuinely unsafe to generate without a compile-run-fix loop against real GPU/KMS hardware. See the module's doc comment. wlr-layer-shellsurfaces are now actually painted (all four layers, correctly interleaved around the window stack via Smithay'sspace_render_elements) - previously the protocol worked but nothing was drawn.- Minimal server-side decorations now render (solid-color grab bar + close
button) for windows that negotiate
Mode::ServerSide- drag to move, click to close. No drawn title text (needs a font-rasterization pipeline this compositor doesn't have yet). - Popup dismiss-on-outside-click is implemented via a simplified manual
check (
HwdeState::dismiss_popups_outside) rather than Smithay's genericPopupGrab, to avoid a wider refactor of the pointer-focus type. - Primary selection ("middle-click paste") is implemented alongside the main clipboard.
- Touch input is forwarded to clients; tablet input and true multi-touch gesture recognition (as opposed to passing pointer-gesture events through during an active grab) are still not implemented.
Shell:
- Wallpaper changes now reach an already-running
comphwdelive via IPC, not just its next restart. - Display management (
display_*commands) only works viaxrandr(X11/nested) - no Wayland-native output management until the DRM backend exists (needs real connector/mode info from KMS). - Language switching is a real, persisted setting with real translations
for English/German/Ukrainian/Spanish (
source-code/fronted/src/ translations/); Polish is the inline default. Coverage is the primary shell chrome (top/bottom bar, launcher, settings) - individual apps are translated incrementally, not all at once.