Elsewindow Application¶
elsewindow starts one remote GUI application and displays its windows
through Xpra. It uses the published
ssh-wrapper package for its
single-master, mux-only OpenSSH lifecycle.
Why The Maintained Xpra Fork Is Required¶
Elsewindow's supported Xpra packages come from the maintained
kogeler/xpra fork, not from an
interchangeable upstream package build. During Elsewindow's implementation,
the required Wayland, GPU, codec, rendering, and remote-application topology
exposed dozens of Xpra defects that prevented the project from operating in
the intended form.
Those defects had three outcomes. Some fixes were contributed directly and accepted upstream. The upstream maintainer fixed others after reports were filed as issues. Some required changes were not accepted; the remaining technical disagreements made continued maintenance of the project fork necessary. The fork therefore carries additional patches required by the reviewed Elsewindow profiles and release-backed live tests.
This is an operational compatibility boundary, not a claim that every Xpra change belongs in Elsewindow. The fork owns its internal patch, codec, GPU, application, and rendering tests. Elsewindow consumes an immutable fork release and tests its public commands and complete SSH-owned lifecycle. Users should not replace that release with a generic upstream build and assume the same behavior.
Requirements¶
Run make runtime-venv before using the launcher. The local and remote systems
need OpenSSH, false, Python 3, and the compatible maintained-fork Xpra
packages. The remote Xpra installation must provide the seamless Wayland
server. The local side needs a working graphical session. The h264 profile
additionally requires a usable DRM render node and a hardware-specific VA-API
driver on both systems.
This repository consumes checksum-bound DEB archives published by
kogeler/xpra. tools/install_xpra_release.py can install the newest owned
release on Debian 13 or Ubuntu 26.04; see
Development. The launcher
itself never installs or changes packages. The installer validates the actual
DEB payload for the native libva encoder and decoder, libyuv, GTK OpenGL,
Wayland, and X11 modules before it can purge an existing installation, and
imports the required modules after APT installs them.
Usage¶
Inspect installed identities and prerequisites without connecting:
elsewindow --diagnose
Use a trusted OpenSSH alias:
elsewindow --ssh-alias workstation -- xterm
Or provide one direct authority:
elsewindow \
--host host.example \
--user desktop-user \
--port 2222 \
-- xterm
The application arguments begin after --. They are validated as data and
converted once to Xpra's --start-child-after-connect value. The application
starts only after the graphical client connects.
Choose one reviewed encoding profile and, when needed, one network profile:
elsewindow \
--ssh-alias workstation \
--encoding-profile h264 \
--network-profile mobile_5g \
-- /opt/application/bin/application
The encoding default is rgb. The network default is the
default_profile declared by the mirrored configuration, currently
gigabit_lan. The user does not select an Xpra backend, display, session name,
title, individual encoder, decoder, colorspace converter, pixel format, or
renderer. The remote backend is always Wayland.
The compositor atomically chooses a free wayland-N socket and publishes it
through displayfd. The launcher validates the owner-controlled session
metadata before attaching. The session name comes from the normalized basename
of the executable, while local windows keep the titles published by the remote
application.
Reviewed Xpra Profiles¶
Two files in kogeler/xpra:develop are the canonical mutable configuration:
fork-maintenance/live-cli.ymlowns the static server/client base, lifecycle, command, diagnostic, encoding, encoder, decoder, CSC, and OpenGL blocks;fork-maintenance/profiles.ymlowns every client-side quality/network profile and its default.
This package ships byte-identical local mirrors at
elsewindow/live-cli.yml and
elsewindow/profiles.yml, because an installed
launcher cannot depend on a fork checkout or a network request. The strict
standard-library loader is the only runtime reader. Python and tests do not
copy the YAML option or numeric tables: tests compare the complete parsed
blocks with the assembled production argv. The same assembler supplies the
live version, server-info, and detach commands, translating only the selected
Wayland display, owned runtime paths, SSH URI, and mux wrapper. Before changing
or reviewing an Xpra argument, first read both current develop files and
compare the mirrors byte-for-byte; synchronize drift before changing the
assembler.
The public encoding mapping is deliberately small:
| CLI value | Canonical transport and policy |
|---|---|
rgb |
rgb.strict |
h264 |
h264.adaptive-alpha |
The strict RGB policy disables video codecs and CSC and uses the non-OpenGL client path. The adaptive-alpha H.264 policy selects native libva H.264, server-side libyuv, and native client OpenGL while retaining the canonical alpha-capable and lossless alternatives declared by the fork.
For H.264, the launcher checks the public local xpra opengl result before
starting the session. Detailed packet, alpha-transition, VA-API, libyuv,
NV12-presentation, application, and rendering acceptance remains exclusively
in the fork that produces the package; this repository consumes the resulting
reviewed profile without reproducing internal Xpra probes.
The network profiles supply only client-side minimum quality, minimum speed, auto-refresh delay, refresh rate, and bandwidth limit. This table is checked against the mirrored YAML so documentation drift fails the repository tests:
| Profile | Minimum quality | Minimum speed | Auto refresh | Refresh rate | Bandwidth limit |
|---|---|---|---|---|---|
gigabit_lan (default) |
90 | 90 | 0.10 s | 60 Hz | unlimited (0) |
fast_wired |
82 | 80 | 0.20 s | 60 Hz | 50 Mbps |
mobile_5g |
78 | 75 | 0.30 s | 45 Hz | 25 Mbps |
mobile_4g |
68 | 70 | 0.45 s | 30 Hz | 8 Mbps |
power_saving |
72 | 70 | 0.50 s | 30 Hz | 8 Mbps |
Production consumes the canonical base, lifecycle, selected transport, and selected network blocks exactly. It excludes fork-only diagnostics and helper commands, translates only the three container-private socket/session paths to the owned remote runtime, and appends this project's no-forwarding and auxiliary-data restrictions plus dynamic session/application values.
The application itself runs on the remote Wayland display. Its Vulkan or OpenGL renderer opens the remote GPU and renders there; Xpra captures the resulting window image and transports picture updates plus control and input over the owned SSH mux. The local machine never receives the application's GL or Vulkan command stream and never receives access to the remote render node.
Lifecycle And Isolation¶
One invocation:
- validates authority, timeouts, application argv, and local Xpra options;
- opens one deliberate foreground OpenSSH ControlMaster;
- validates the remote public
seamlesscommand and required options through that master's mux socket; - starts a foreground Wayland Xpra server in one heartbeat-supervised remote process group;
- reads and validates the display selected through
displayfd; - attaches one local Xpra client through the same mux socket.
The server cannot adopt an existing display. It binds no Xpra TCP listener. OpenSSH forwarding, agent sharing, X11 forwarding, automatic reconnection, fallback authentication, Xpra audio, webcam, printing, file transfer, URL and file opening, notifications, HTML, SSH upgrades, D-Bus, and additional command startup are disabled.
Normal detach, application exit, cancellation, SIGINT, SIGTERM, lease
expiry, or SSH-master loss enters the same idempotent cleanup. The local client
stops first. The remote supervisor then terminates only its recorded process
group and removes its sockets and private runtime state. It never searches by
executable name or modifies an unrelated Xpra session.
Applications that double-fork, move to another cgroup or session, or delegate to an already-running single-instance process can escape this ownership boundary. Use an application option that creates a fresh foreground instance.
Options And Errors¶
The lifecycle timeout options are:
| Option | Default |
|---|---|
--connect-timeout |
120 seconds |
--ready-timeout |
45 seconds |
--probe-timeout |
8 seconds |
--poll-interval |
1 second |
--heartbeat-interval |
10 seconds |
--lease-timeout |
45 seconds |
--cleanup-grace |
5 seconds |
Stable failures include missing_dependency, connection_start_failed,
connection_lost, xpra_probe_timeout, xpra_ready_timeout,
xpra_identity_mismatch, xpra_client_failed, and xpra_server_exited.
Public errors omit private control paths and full subprocess argv. Selected
Xpra diagnostics are bounded, stripped of control characters, and scrubbed of
private runtime paths.
Release-backed Image Verification¶
make xpra-images freshly resolves the newest canonical kogeler/xpra
package release, validates both distribution archives, and prepares matching
Ubuntu 26.04 target and Debian 13 client images. Build inputs and connection
material are streamed through validated archives; no host path is bind-mounted
and podman cp is not used. Consumers execute the images by immutable image ID
and can require the same release ID, commit, version, package set, and asset
provenance on both sides.
make live-test first builds and verifies the Python distribution. Its client
payload excludes the source package, installs that wheel into the disposable
account, and asserts the installed module path, version metadata, wrapper
version, and both resources before any lifecycle case. Thus the live result is
packaged-product evidence, not an editable-checkout result.
Codec, GPU, application, and direct-Xpra behavioral acceptance belongs to
kogeler/xpra:develop under fork-maintenance/. This project verifies the
profile loader, exact argv assembly, owned SSH/Xpra lifecycle, package release
contract, and image provenance without redefining the fork's codec tests.