Commit graph

57 commits

Author SHA1 Message Date
Till Wegmueller
70859175c0 Add doors IPC transport for illumos, simplify client binaries
Add platform-aware IPC transport layer for the launcher protocol:

- transport module: send_request_sync() auto-selects doors (illumos)
  or Unix sockets (Linux) at compile time
- doors_transport: uses doors::Client for high-speed synchronous RPC,
  gated behind cfg(target_os = "illumos") + "doors" feature flag
- unix_transport: blocking Unix socket client for all platforms

Simplify client binaries to use the sync transport:
- wradm: drops tokio dependency entirely, now fully synchronous
- wrlogin: drops tokio dependency, uses sync transport
- wrsessd: uses shared default_ipc_path() for consistency

The doors crate (0.8.1) is an optional illumos-only dependency.
On Linux, all code compiles and tests pass with Unix socket transport.
2026-04-09 22:21:14 +02:00
Till Wegmueller
f6b9ea56ba Add session launcher, greeter, admin CLI, and session config
Session infrastructure for the launcher/greeter architecture (Phase 3):

- Launcher protocol: JSON-over-Unix-socket messages (LauncherRequest/
  LauncherResponse) for session_requested, session_authenticated,
  session_logout, plus admin queries (list_sessions, kill_session)

- Session config: ~/.config/wayray/session.toml with wm, panel,
  launcher, notifications, and autostart fields. Serde TOML parsing
  with sensible defaults (wr-wm-floating). 5 unit tests.

- wrsessd: Session launcher daemon listening on Unix socket. Manages
  per-token sessions, launches greeter on session_requested, starts
  desktop components from session.toml on session_authenticated,
  cleans up child processes on logout. Admin query support.

- wrlogin: Reference CLI greeter. Reads credentials from stdin,
  sends session_authenticated to wrsessd, exits on success.
  Token passed via WAYRAY_SESSION_TOKEN env var.

- wradm: Session management commands (list, kill) communicating
  with wrsessd via launcher protocol. Tabular output format.
2026-04-09 21:22:46 +02:00
Till Wegmueller
d59411ca60 Add session lifecycle, token-based identity, and client token support
Core session management infrastructure for Phase 3:

- Session module: SessionId, SessionToken, SessionState enum with
  validated transitions (Creating→Active⇄Suspended→Destroyed),
  Session struct with timeout tracking, SessionRegistry with O(1)
  lookup by ID and token (10 unit tests)

- Protocol: ClientHello gains optional token field, ServerHello gains
  resumed flag and token echo, SessionStatus/SessionEvent enums added
  to ControlMessage for session state notifications

- Server: SessionRegistry in headless CalloopData, sessions created on
  client connect (with token lookup for resumption), suspended on
  disconnect (not destroyed), periodic cleanup of expired sessions

- Client: --token CLI flag, persistent token at ~/.config/wayray/token
  with auto-generation (random 16-byte hex), token sent in ClientHello,
  resumed state logged from ServerHello
2026-04-09 21:14:48 +02:00
Till Wegmueller
04b8b2f28b Update roadmap: track remaining WM protocol TODOs in correct phases
- Phase 3.2: workspace protocol implementation (create/destroy/assign/tags)
- Phase 5.1: WM protocol completion (relative z-order, borders, multi-output,
  interactive move/resize, ProtocolAdapter)
- Renumber sections to accommodate new entries
2026-04-07 22:58:05 +02:00
Till Wegmueller
f648a8af39 Wire WM protocol requests to compositor and add keybinding support
Complete the Phase 2.5 protocol wiring so external WMs can actually
control the compositor:

- Add compositor action methods to WmProtocolHandler: configure_window,
  focus_window, close_window, set_fullscreen, set_decoration
- Wire manage-phase requests (propose_dimensions, set_focus, close,
  fullscreen grant/deny, decorations) through to Smithay ToplevelSurface
- Trigger manage_start on new toplevel, render_start each frame, and
  notify_window_closed on toplevel destruction when external WM connected
- Apply external WM render commands in headless render loop
- Keybinding dispatch: bind_key/unbind_key storage, mode support,
  binding_pressed/released events sent to WM seat
- Built-in floating WM: Alt+F4 close, Alt+Tab focus cycling with tests
2026-04-07 22:51:50 +02:00
Till Wegmueller
f2aebe04a6 Implement pluggable window management protocol (Phase 2.5)
Add a custom Wayland protocol (wayray_wm_v1) that allows external
window manager processes to control layout, focus, and keybindings
in the WayRay compositor, inspired by River's two-phase transaction
model.

New crates:
- wayray-wm-protocol: Wayland protocol XML + generated server/client
  bindings via wayland-scanner for four interfaces (manager, window,
  seat, workspace)
- wr-wm-tiling: Reference BSP tiling WM demonstrating the protocol

Compositor changes:
- WindowManager trait + WmState coordinator abstracts WM behavior
- Built-in floating WM (centered windows, click-to-focus, z-ordering)
- Protocol server with GlobalDispatch/Dispatch for all interfaces
- Hot-swap (replaced event) and crash resilience (fallback to built-in)
- new_toplevel delegates to WM instead of hardcoding 800x600 at (0,0)
- WM render phase integrated into headless frame pipeline
2026-04-07 22:29:19 +02:00
Till Wegmueller
a7ad184774 Use EventLoopProxy for efficient frame wake instead of busy-poll
Replace ControlFlow::Poll (CPU-hungry busy loop) with an
EventLoopProxy that the network thread uses to wake the winit
event loop only when a new frame arrives. Zero CPU when idle,
instant wake on new frames.
2026-04-07 19:49:33 +02:00
Till Wegmueller
b805f9f6c8 Fix typing lag: use ControlFlow::Poll for continuous frame updates
The winit event loop defaulted to Wait mode, only processing frames
when user input arrived. Switch to Poll so the loop continuously
checks for new frames from the network thread.
2026-04-07 19:44:39 +02:00
Till Wegmueller
974511277b Fix keycode mapping, client disconnect, and server shutdown
- Keycodes: add +8 offset for XKB (evdev scancode + 8 = XKB keycode)
- Client: force exit on Cmd+Q/close (network thread may block)
- Server: force exit on Ctrl+C (network thread may block on accept)

Proper graceful shutdown with tokio CancellationToken deferred.
2026-04-07 19:37:41 +02:00
Till Wegmueller
c4e3920c79 Fix client surface rendering: add window.on_commit() and space.refresh()
Root cause: Window::bbox() stayed at 0x0 because Window::on_commit()
was never called after surface commits. The Space then never associated
the window with the output (no overlap), so render_elements_for_output
returned empty.

Two fixes:
- Call window.on_commit() in CompositorHandler::commit() to update
  the window's bounding box from the committed surface tree
- Call space.refresh() each frame to update output-element mappings

Also: send xdg_toplevel configure with suggested 800x600 size.
2026-04-07 19:15:52 +02:00
Till Wegmueller
8d248a8f52 Debug: send initial configure in new_toplevel, add window state logging
- Send xdg_toplevel configure before mapping window (foot needs this)
- Add window bbox and configure state debug logging
- Still investigating: foot connects but bbox stays 0x0 (no buffer committed)
2026-04-07 18:59:17 +02:00
Till Wegmueller
9fc27d3b56 Fix PixmanRenderer compositing: remove EGL features from default build
renderer_gl and backend_winit pulled in backend_egl, which changed the
ImportAll blanket impl to require ImportEgl — a trait PixmanRenderer
doesn't implement. This caused render_output to silently skip client
surface compositing (only the clear color rendered).

Fix: move renderer_gl and backend_winit behind a "winit" cargo feature.
Default build uses only renderer_pixman, which satisfies ImportAll via
the simpler ImportMemWl + ImportDmaWl blanket impl.

Winit backend: cargo build -p wrsrvd --features winit
Headless (default): cargo build -p wrsrvd
2026-04-07 18:44:19 +02:00
Till Wegmueller
3c6430c982 Add framebuffer content debug check (temp diagnostic) 2026-04-07 18:34:25 +02:00
Till Wegmueller
6968bcd69c Fix stride handling and add render debug logging
Use pixman Image's actual stride instead of width*4 for pixel reads.
Add debug logging for element count and damage presence per frame.
2026-04-07 18:26:07 +02:00
Till Wegmueller
8bd8f2490c Read pixels directly from pixman Image instead of ExportMem
ExportMem::copy_framebuffer may not capture composited client surfaces.
Read pixels directly from the pixman Image's CPU memory after rendering,
since PixmanRenderer composites in-place. This should fix missing
client windows in the remote display.
2026-04-07 18:16:05 +02:00
Till Wegmueller
fa6bb53142 Fix pixel format: pass ARGB8888 directly as BGRA8
On little-endian x86, ARGB8888 bytes in memory are [B,G,R,A] which
matches wgpu's Bgra8Unorm layout. No byte swapping needed.
2026-04-07 18:11:47 +02:00
Till Wegmueller
6b15ee819e Fix black screen: convert ARGB8888 to BGRA8 in client display
Server (PixmanRenderer) outputs ARGB8888, client GPU texture expects
BGRA8. Added byte-order conversion in update_frame(). Also changed
texture format from Bgra8UnormSrgb to Bgra8Unorm for correct colors.
2026-04-07 18:06:41 +02:00
Till Wegmueller
ab8f9e0d03 Support DNS hostnames in wrclient server address
resolve_server_addr() handles both IP:port and hostname:port via
std::net::ToSocketAddrs. Server name passed through for TLS SNI.
2026-04-07 17:59:22 +02:00
Till Wegmueller
43a4d7e6af Add missing display.rs and wrclient display dependencies
display.rs (winit + wgpu renderer) and Cargo.toml changes (winit,
wgpu, pollster, env_logger) were created but not committed in the
Task 5 subagent.
2026-04-07 17:51:40 +02:00
Till Wegmueller
564c473ab4 Wire end-to-end frame encoding and network into headless backend
Start QUIC server in wrsrvd main.rs before dispatching to backend,
passing NetworkHandle to the headless backend. The headless render loop
now encodes each frame as XOR diff against the previous frame, compresses
damage regions with zstd, and sends FrameUpdate messages to connected
clients via the network channel.

Network input from remote clients is drained each iteration of the main
event loop and injected into the compositor via inject_network_input().
Connection state (client connected/disconnected) is tracked to avoid
encoding frames when no client is listening.
2026-04-07 17:08:55 +02:00
Till Wegmueller
eb8394d247 Add input forwarding from wrclient to wrsrvd
Implement client-side input capture (input.rs) that converts winit
WindowEvents to protocol InputMessages: keyboard via evdev keycode
mapping, pointer motion/buttons/axis. Wire into wrclient main.rs
event handler to send input over QUIC via the existing input channel.

Server-side: add inject_network_input() to WayRay state that accepts
protocol InputMessages and injects them into the Smithay seat, following
the same patterns as process_input_event for keyboard, pointer motion
with surface focus, click-to-focus, and axis scroll.

Also upgrade client frame handling to use persistent framebuffer with
XOR-diff decoding via wayray_protocol::encoding::apply_region.
2026-04-07 17:08:47 +02:00
Till Wegmueller
f79a934c2b Add QUIC transport layer with quinn for server and client
Implement QUIC networking for wrsrvd (server) and wrclient (client) using
quinn over rustls with self-signed certificates. Three logical channels:
control (bidirectional), display (server->client unidirectional), and
input (client->server unidirectional).

Server runs tokio in a background thread, communicating with the compositor
via std::sync::mpsc channels. Client exposes an async connect() API that
returns a ServerConnection with methods for sending input and receiving
frames.

Key design note: quinn streams are lazily materialized -- accept_bi/
accept_uni on the peer won't resolve until data is written. The handshake
protocol accounts for this by having each side write immediately after
opening streams.
2026-04-07 16:54:01 +02:00
Till Wegmueller
8a3d14ff19 Add headless backend with PixmanRenderer, refactor into backend modules
Restructure wrsrvd to support two backends: a headless PixmanRenderer
(default) for running without a display server, and the existing Winit
backend (via --backend winit). The render logic is split into per-backend
modules, and the old render.rs is removed.
2026-04-07 16:29:32 +02:00
Till Wegmueller
f394d8cd7d Add XOR diff + zstd frame encoding in wayray-protocol
Encoder: xor_diff + encode_region (per damage rectangle).
Decoder: apply_region (decompress + XOR apply to framebuffer).
Both live in wayray-protocol::encoding for shared access.
14 tests including 3 end-to-end round-trip integration tests.
2026-04-07 15:42:54 +02:00
Till Wegmueller
0762cb1fa3 Implement wire protocol messages and codec in wayray-protocol
Message types for control, display, and input channels with serde
derives. Length-prefixed postcard codec with encode/decode/framing.
Seven round-trip tests covering all message types and edge cases.
2026-04-07 15:35:48 +02:00
Till Wegmueller
8d8af48676 Add Phase 1 remote display pipeline implementation plan 2026-04-07 15:32:19 +02:00
Till Wegmueller
f0c367c829 Add Phase 1 remote display pipeline design spec 2026-04-07 15:09:03 +02:00
Till Wegmueller
547d62ca1e Fix VM setup: add X11 fallback, libxkbcommon-x11
- Add libxkbcommon-x11-0, xorg, xinit, openbox, xterm packages
- Document X11 as primary path (virgl EGL broken under UTM)
- Keep Sway as Option B for non-virtualized environments
2026-04-07 14:31:12 +02:00
Till Wegmueller
84c479eaca Switch VM setup from Arch Linux to Ubuntu 22.04
Arch ARM tooling has limited support on UTM/Apple Silicon.
Ubuntu 22.04 gallery image works out of the box.

- setup.sh: apt-get packages, Ubuntu paths (/sbin/agetty, .profile)
- README.md: UTM gallery workflow instead of manual ISO install
- Default repo URL: github.com/CloudNebulaProject/wayray
2026-04-07 13:41:22 +02:00
Till Wegmueller
0fa1f63c8a Add VM testing setup for Arch Linux aarch64 via UTM
- vm/setup.sh: Idempotent provisioning script that installs Wayland
  stack, Rust toolchain, builds WayRay, configures auto-login + Sway
- vm/README.md: Step-by-step UTM VM creation and testing guide
2026-04-04 20:59:42 +02:00
Till Wegmueller
258435cb04 Add Phase 0.5 VM testing implementation plan 2026-04-04 20:57:51 +02:00
Till Wegmueller
e5ad9349bb Add Phase 0.5 VM testing setup design spec 2026-04-04 20:50:53 +02:00
Till Wegmueller
9ab3e6d782 Remove dead code and fix all clippy/fmt warnings
- Remove CapturedFrame struct and last_capture field (no consumer yet)
- Remove display_handle field (re-obtainable when needed)
- Prefix output_manager_state and xdg_decoration_state with _ (kept
  alive for Wayland globals but not directly read)
- Keep framebuffer capture logging to verify ExportMem path works
2026-04-04 19:07:46 +02:00
Till Wegmueller
5fee1a9b40 Fix review findings: output transform, resize TODO, import aliases
- Change Transform::Flipped180 to Transform::Normal for virtual output
- Add TODO comment on resize handler for future output mode update
- Rename misleading JsonPointer* import aliases to *Trait
2026-04-04 19:03:14 +02:00
Till Wegmueller
ed2f9be8e6 Add missing delegates and framebuffer capture for functional compositor
- Add PrimarySelectionState and delegate: terminals like foot expect
  the primary selection protocol to be present
- Add XdgDecorationState and delegate: allows clients to negotiate
  server-side vs client-side window decorations
- Send initial configure for popups so menus and tooltips render
- Flatten nested if-let chains in commit handler (clippy)
- Include framebuffer capture in render pipeline (from prior task):
  copies rendered frame via ExportMem for future network transport
2026-04-04 18:59:49 +02:00
Till Wegmueller
a189c2f51b Add keyboard and pointer input handling via Smithay seat
Initialize keyboard and pointer on the Wayland seat at startup, and
route Winit input events (keyboard, pointer motion, button, scroll)
through process_input_event to the Smithay seat so clients can receive
input. Click-to-focus raises the clicked window and sets keyboard focus.
2026-04-04 18:51:22 +02:00
Till Wegmueller
cbfc6e95df Add rendering pipeline for client surfaces via OutputDamageTracker
- Create render module using Smithay's desktop::space::render_output
  for damage-tracked frame rendering to the Winit backend window
- Store backend and damage_tracker in CalloopData so the Winit event
  callback can trigger rendering on Redraw events
- Send initial xdg toplevel configure on first commit so clients can
  begin drawing
- Send frame callbacks after each render so clients schedule redraws
2026-04-04 18:45:31 +02:00
Till Wegmueller
50c8f68906 Wire up Winit backend and calloop event loop for wrsrvd
Initialize WinitGraphicsBackend with GlesRenderer, create a virtual
Output matching the window size, set up a Wayland listening socket via
ListeningSocketSource, and run the main event loop through calloop with
WinitEventLoop as an event source. The compositor now opens a window
and accepts Wayland client connections.
2026-04-04 18:38:38 +02:00
Till Wegmueller
383e91addf Split Wayland protocol handlers into dedicated modules
Move handler trait impls and delegate macros from state.rs into
handlers/{compositor,xdg_shell,input,output}.rs. Flesh out
CompositorHandler::commit with on_commit_buffer_handler and
XdgShellHandler::new_toplevel with window mapping. Add DataDeviceHandler,
SelectionHandler, ClientDndGrabHandler, and ServerDndGrabHandler impls
with DataDeviceState in the WayRay struct. State.rs now contains only
the struct definition and constructor.
2026-04-04 18:30:32 +02:00
Till Wegmueller
1f44288bce Add WayRay compositor state struct with Smithay subsystems
Define the central WayRay state struct holding all Smithay subsystem
states (compositor, xdg_shell, shm, seat, output, space, clock) and
wire Display creation into main.rs. Includes minimal handler trait
impls and delegate macros needed to compile; these will be expanded
and moved to a handlers module in Task 4.
2026-04-04 18:26:03 +02:00
Till Wegmueller
2d68ab6e8d Add tracing and miette error infrastructure to wrsrvd 2026-04-04 18:20:52 +02:00
Till Wegmueller
4e08dfb5a9 Set up Cargo workspace with four crates
Workspace: wrsrvd, wrclient, wayray-protocol, wradm under crates/.
Smithay configured with default-features=false, portable features only.
Implements ADR-007 project structure.
2026-04-04 18:16:53 +02:00
Till Wegmueller
e55df6306d Add Phase 0 foundation implementation plan
Detailed 9-task plan covering workspace scaffold, Smithay compositor,
Wayland protocol handlers, Winit backend, rendering, input handling,
and framebuffer capture with ExportMem.
2026-04-04 18:08:32 +02:00
Till Wegmueller
f3f584e8a7
Add article: WayRay as a modern successor to Sun Ray
Long-form article for the project website covering SunRay history,
why it mattered, what went wrong, and how WayRay modernizes every
aspect: QUIC transport, content-adaptive encoding, smartphone
proximity tokens, pluggable window management, federation, protocol
gateways, and illumos as primary platform.
2026-03-29 17:08:48 +02:00
Till Wegmueller
f702cbf4e7
Add ADR-016: GPU pipeline future-proofing for cloud gaming
Ensure today's CPU-first design doesn't block a future zero-copy
GPU encoding path (DMA-BUF → VAAPI/NVENC, sub-5ms encode latency).

Key design constraints:
- FrameSource enum: Cpu and DmaBuf variants (build Cpu now, DmaBuf later)
- FrameEncoder trait: accepts both, encoder picks preferred source
- Pipelined render→encode→send (no synchronous blocking)
- Adaptive frame cadence: OnDamage (desktop) vs Fixed (gaming)
- Damage tracking forks: pixel diff for CPU, Wayland hints for GPU

No GPU code built now -- just trait interfaces that preserve the path.
2026-03-29 13:29:32 +02:00
Till Wegmueller
643c4f042d
Rename binaries to illumos-style short names
Follow illumos CLI naming conventions (zoneadm, svcadm, dladm):

  wayray-server           → wrsrvd
  wayray-client           → wrclient
  wayray-ctl              → wradm
  wayray-greeter          → wrlogin
  wayray-session-launcher → wrsessd
  wayray-gateway          → wrgw
  wayray-wm-floating      → wr-wm-floating
  wayray-wm-tiling        → wr-wm-tiling

Updated across all 23 documentation files, ADRs, book pages,
roadmap, and CLAUDE.md. Added binary name table to CLAUDE.md.
2026-03-29 00:34:19 +01:00
Till Wegmueller
c32ed5531d
Add ADR-015: Virtual desktops, RDP integration, and protocol gateways
Three-tier RDP integration:
- Tier 1: FreeRDP as Wayland app (works today)
- Tier 2: FreeRDP RAIL mode (seamless Windows apps in WM)
- Tier 3: Protocol gateway (VPN + RDP + seamless, managed service)

Protocol gateway handles full lifecycle: VPN tunnel establishment,
RDP session start, RAIL window translation to foreign surfaces.
Each gateway in isolated network namespace/zone. Connection profiles
per customer with security policies (clipboard, file transfer, etc.)

Protocol-agnostic adapter trait supports RDP, VNC, SPICE, SSH X11,
and WayRay federation as pluggable remote protocol sources.

Includes "maintenance engineer's day" scenario showing multi-customer
workflow with virtual desktops, gateway connections persisting across
session suspend/resume, and cross-site mobility.
2026-03-29 00:31:00 +01:00
Till Wegmueller
204c200bc9
Add direct remote access scenario and token-based server routing
When at a friend's or customer's site, the client connects directly
to the user's own server over the internet -- no local server involved,
no federation needed. The thin client is just a screen + network.

- ADR-014: Add scenarios 4b/4c (friend's house, BYOD on-site),
  server selection UI, three-category taxonomy (direct remote,
  federation, sandboxing)
- ADR-013: BLE beacon payload now includes server address so the
  phone tells any terminal where to find the user's desktop
2026-03-29 00:08:34 +01:00
Till Wegmueller
8653c01518
Add ADR-014: Federation and foreign surface integration
Unified mechanism for two related problems:
- Federation: windows from remote WayRay servers appear in local
  desktop (B2B invites, cross-org app sharing, visiting consultants)
- Sandboxing: windows from isolated local environments (illumos zones,
  containers) appear alongside trusted local windows

Three display modes:
- Desktop-in-desktop (full remote session in a window)
- Merged windows (seamless per-window integration with local WM)
- App embedding (future: subsurface portal)

Trust-level visual indicators (Local/Trusted/Sandboxed/Untrusted),
input isolation per trust level, B2B invite flow, server-to-server
mutual TLS federation, and OIDC-based dynamic trust chains.

Same ForeignWindow protocol for both remote (QUIC) and local (Unix
socket) sources. illumos zones as natural sandboxing primitive.
2026-03-29 00:03:51 +01:00
Till Wegmueller
141f8220d7
Update ADR-013: NFC charging pad as smart card reader
Add wireless charging pad mode -- phone on Qi pad acts as smart card
in a reader slot. NFC provides crisp insert/remove semantics without
RSSI ambiguity. Combined NFC+BLE mode for heartbeat during brief
NFC interrupts. Configurable per-deployment: centimeter range (pad)
vs meter range (pocket) vs combined.
2026-03-28 23:28:55 +01:00