Skip to content

HackerOS-Linux-System/HWDE

Repository files navigation

HWDE - HackerOS Wayland Desktop Environment

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).

Layout

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`, ...

Building

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 wallpaper

Requirements: 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 be cargo 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. Run cargo check --workspace first on a machine with Rust >= 1.80.

starthwde usage

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.

comphwde <-> starthwde integration

They talk over a small NDJSON protocol on a Unix socket (ipc/, package hwde-ipc). As of v0.1:

  • starthwde spawns comphwde and 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 in BottomBar.tsx shows and controls both in-shell app windows and external ones - external windows are tracked compositor-side (ManagedWindow in compositor/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.

Important fix: commands were freezing the whole shell

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).

Storage locations

  • ~/.config/HWDE/settings.hk - small settings (theme, wallpaper, icon theme, launcher icon, language), using the real hk-parser crate for the HackerOS .hk format.
  • ~/.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 .desktop scan results (see desktop_entries.rs); refresh from Settings -> Aplikacje.

Wallpaper & icons

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 in images/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), then hicolor/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.

App launcher

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).

Known scope / what's next (v0.2 candidates)

Compositor:

  • Still only the windowed (winit) backend is wired into main. compositor/src/backend_drm.rs now has real session/udev-hotplug/ libinput code (ported from Smithay's anvil reference 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-shell surfaces are now actually painted (all four layers, correctly interleaved around the window stack via Smithay's space_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 generic PopupGrab, 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 comphwde live via IPC, not just its next restart.
  • Display management (display_* commands) only works via xrandr (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.