Commit Graph

4040 Commits

Author SHA1 Message Date
Geoffrey McRae
6c0f8d8a28 [client] control: test config and resize messages 2026-08-12 05:05:26 +10:00
Geoffrey McRae
7dc6bc8527 [client] lgmp: test input ownership lifecycle 2026-08-12 05:05:26 +10:00
Geoffrey McRae
ff47bf6128 [client] spice: test session and surface lifecycle 2026-08-12 05:05:26 +10:00
Geoffrey McRae
0d870146b5 [client] clipboard: test provider lifecycle 2026-08-12 05:05:26 +10:00
Geoffrey McRae
28df55e51c [client] egl: test desktop damage geometry 2026-08-12 05:05:26 +10:00
Geoffrey McRae
dea5706667 [client] input: test provider handoff and rollback 2026-08-12 05:05:26 +10:00
Geoffrey McRae
223bb6fd58 [client] scheduler: test frame control lifecycle 2026-08-12 05:05:26 +10:00
Geoffrey McRae
8bf7c5b49e [client] audio: test streams and microphone consent 2026-08-12 05:05:26 +10:00
Geoffrey McRae
49fa27b573 [client] lgmp: test frame validation and leases 2026-08-12 05:05:26 +10:00
Geoffrey McRae
c0ea0368c6 [client] transport: test fallback lifecycle 2026-08-12 05:05:26 +10:00
Geoffrey McRae
b146c0168a [client] tests: cover render source queue 2026-08-12 05:05:26 +10:00
Geoffrey McRae
f1615aa333 [client] display: stop callbacks before state teardown
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
2026-08-12 03:08:49 +10:00
Geoffrey McRae
ebc9d076ec [client] overlay: clean up partial initialization 2026-08-12 03:08:49 +10:00
Geoffrey McRae
6ddf1d62cd [client] wayland: clean up failed window initialization 2026-08-12 02:56:05 +10:00
Amit Mendapara
8187177c7f [client] app: free overlays after display server shutdown
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
The render thread freed the overlays as soon as it exited, while the
main thread could still be dispatching display server input callbacks
that iterate them. Free the overlays in lg_shutdown instead, once the
render thread has been joined and the display server has shut down.

The overlays now outlive the renderer, so overlayFreeImage must not
call into it; renderer deinitialization has already destroyed all
textures along with the context.
2026-08-12 02:50:01 +10:00
Amit Mendapara
75f7d614a7 [client] evdev: split teardown into stop and free phases
evdev_stop was never called, and calling it revealed unsafe teardown:
the device list was freed before the thread was joined, a zero epoll
descriptor was mistaken for a valid one, and the device loops walked
past the end of the array through a sentinel that does not exist.

Join the thread in evdev_stop and defer the rest to the new evdev_free.
The display server grab hooks route into evdev until its event thread
is joined, so the device state must stay valid until the display
server has been freed; evdev_free then restores the hooks and releases
the state.
2026-08-12 02:50:01 +10:00
Amit Mendapara
c66a974f1d [client] wayland: marshal resize requests to the event-loop thread
setWindowSize is called from the render, frame and transport threads,
but shellResize issues shell requests and, with the libdecor GTK
plugin, renders the window decorations through pango, none of which is
thread safe. A frame thread exiting after such a call crashed in the
pango fontmap destructor during thread teardown.

Publish the requested size atomically and wake the event loop through
an eventfd registered in the epoll; the poll callback applies the size
on the event-loop thread. Concurrent requests coalesce into the most
recent one.
2026-08-12 02:50:01 +10:00
Geoffrey McRae
574e8edbae [client] transport: recover incompatible sessions
Report expected and current protocol versions through the transport
interface and expose session-independent recovery operations.

Offer recovery from the version mismatch popup, publish requests through
the reserved IVSHMEM channel, and select the validated SPICE fallback.
2026-08-12 00:05:24 +10:00
Geoffrey McRae
bacf376305 [idd] recovery: restore fallback display
Add a protocol-independent recovery channel outside LGMP so clients can
request a usable guest display even when transport versions differ.

Synchronize recovery state with the helper across driver restarts and
restore the configured topology without persisting temporary changes.
2026-08-11 23:50:13 +10:00
Geoffrey McRae
9898e9bcec [common/idd] recovery: reserve IVSHMEM control region
Define a fixed, protocol-independent recovery ABI in the final 64 KiB
of IVSHMEM.

Provide crash-safe multi-client requests and coherent producer status.

Exclude the region from LGMP allocation and frame capacity so future
protocol mismatches retain a stable control path.
2026-08-11 23:50:13 +10:00
Geoffrey McRae
61a49ebaba [idd] common: use CSRWLock throughout the drivers
Make CSRWLock own the native lock and provide scoped guards for shared,
exclusive, early-unlock, and non-blocking use.

Replace direct SRW lock management throughout the IDD, input driver,
and helper while preserving the existing lock scopes.
2026-08-11 23:50:13 +10:00
Geoffrey McRae
2543366f5f [doc] words: add missing words 2026-08-11 21:19:59 +10:00
Geoffrey McRae
33bdc611d8 [docs] guide: document current Looking Glass features 2026-08-11 20:46:46 +10:00
Geoffrey McRae
45429681a0 [client] spice: own transport configuration
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Register SPICE connection and component options in the SPICE transport.
Move generic input and clipboard settings out of the SPICE namespace,
while retaining migration aliases for existing configurations.

Keep PureSpice and usbredir build requirements private to the transport,
and remove obsolete SPICE configuration state from the client core.
2026-08-11 18:31:19 +10:00
Geoffrey McRae
1a6f85eae2 [client] video: switch transport sources
Track primary and fallback video with source-specific generations, and
publish a source only after its first frame or software surface is
ready.

Route SPICE surfaces and cursors through the generic render queue. Keep
the current image across handoffs, and switch input only after the new
source has been presented.

Move fallback activation to its worker so display callbacks cannot
block or deadlock the render path.
2026-08-11 18:31:19 +10:00
Geoffrey McRae
053d4e9d9b [client] transport: manage persistent fallback sessions 2026-08-11 16:16:19 +10:00
Geoffrey McRae
5b12685e3c [client] spice: move protocol into transport 2026-08-11 15:33:53 +10:00
Geoffrey McRae
2bd0db1a26 [client] renderers: generalize software surface updates 2026-08-11 15:07:35 +10:00
Geoffrey McRae
5cf5dcfe05 [client] providers: handle fallback disconnects safely 2026-08-11 15:06:45 +10:00
Geoffrey McRae
96a5cf4ce8 [client] transport: split video provider operations 2026-08-11 15:05:00 +10:00
Geoffrey McRae
eb6bb78db9 [client] transport: encapsulate transport instances 2026-08-11 14:53:29 +10:00
Geoffrey McRae
77b661194a [client] input: fix automatic keyboard capture
Treat autoCapture as keyboard ownership while the pointer is inside the
guest viewport. Predict the next local position for both absolute and
relative motion, then release the keyboard before the pointer crosses
an edge.

Keep capture, focus, and deferred evdev transitions consistent while
retaining the latest local position as the prediction baseline.
2026-08-11 14:43:48 +10:00
Geoffrey McRae
d20904e3af [client] input: stop absolute cursor feedback
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
X11's legacy guest-position synchronization warps the host cursor to
delayed guest updates. With absolute input this feeds old positions back
through cooked motion and pulls the cursor away from window edges.

Skip display-server guest synchronization when the active input is
absolute. Relative input and explicit uncapture alignment are unchanged.
2026-08-10 19:29:22 +10:00
Geoffrey McRae
89dcf56073 [client] X11: release pointer after capture
Normal input now uses absolute positioning, so retaining the XI pointer
grab after capture leaves no later path to release it.

Always release the grab so leaving the window works again and the
uncapture path can align the host cursor to the guest position.
2026-08-10 18:47:27 +10:00
Geoffrey McRae
4afb0254d1 [client] X11: test grabbed input routing
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Keep raw and cooked event selection inside the tested X11 policy.

Exercise grab transitions and held-key normalization directly.
2026-08-10 18:19:33 +10:00
Geoffrey McRae
15e0cbbcc4 [client] X11: synchronize keyboard input state
Replay held keys after focus enters the client window.

Track modifiers and lock LEDs for cooked and grabbed raw input.

Handle external XKB indicator changes while the window stays focused.
2026-08-10 17:36:21 +10:00
Geoffrey McRae
f8c4ef3360 [client] X11: match Wayland pointer input behaviour
Make cooked mouse input independent of keyboard focus.

Preserve button state across pointer leave events.

Match Wayland event order, wheel steps, and raw motion delivery.
2026-08-10 17:20:47 +10:00
Geoffrey McRae
b8955fd012 [client] input: add display server behaviour tests
Extract input policy from the Wayland and X11 protocol handlers.

Exercise both implementations against literal Wayland event traces.
2026-08-10 17:15:35 +10:00
Geoffrey McRae
802c8b5803 [client] PureSpice: avoid blocking record writes
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Update PureSpice so microphone delivery cannot hold audio backend
shutdown behind a busy socket. Record packets now use a bounded
nonblocking write with framing-safe failure handling.
2026-08-10 16:36:36 +10:00
Geoffrey McRae
87aa61510c [client] audio: harden low-latency streaming
Rework audio provider and backend lifecycles so playback and capture
callbacks quiesce without blocking real-time threads. Move activation,
teardown, controls, retries, and diagnostics onto bounded workers.

Harden USB audio cadence, feedback, and capture recovery.
Preserve source clocks through recording and pace packets from the
device clock. Bound queues, waits, conversion buffers, and packet sizes.

Make PipeWire and PulseAudio stream control thread-safe and recoverable.
Correct latency clock domains, coalesce rate updates, preserve recent
capture under overload, and keep logging outside real-time callbacks.
2026-08-10 16:36:12 +10:00
Geoffrey McRae
4434985aa3 [client] usb audio: add microphone recording
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Add a composite UAC2 microphone function with its own clock so
recording and playback can use independent sample rates.

Packetize asynchronous capture through usbredir, follow the host
capture clock, and preserve the newest frames across stalls.

Reconfigure active recording without another permission prompt and
fix lost PipeWire capture wakeups.
2026-08-10 06:32:05 +10:00
Geoffrey McRae
d660574a93 [client] audio: recover immediately from provider underruns
Treat a negative provider-controlled playback ring as a timeline
discontinuity rather than carrying its underrun debt.

Rebase to the normal low-water target and reset feedback correction so
guest stalls resume at low latency instead of discarding audio for
seconds.
2026-08-10 05:29:39 +10:00
Geoffrey McRae
73b15e4723 [client] usbredir: gracefully disconnect USB devices
Wait for the usbredir disconnect acknowledgement before closing SPICE.

Block replug while removal is pending and bound the shutdown wait.
2026-08-10 05:01:55 +10:00
Geoffrey McRae
2ca2553086 [client] audio: limit timing graph update rate
Sample the playback ring graph at its original 40 Hz rate so its
1,200 entries continue to represent 30 seconds of history.

Keep packet processing and asynchronous USB feedback at full rate.
2026-08-10 04:49:34 +10:00
Geoffrey McRae
0f3c1db261 [client] usb audio: add asynchronous clock feedback
Advertise an asynchronous UAC2 OUT endpoint with explicit feedback so
Windows paces USB audio from the host playback clock.

Drive feedback from measured backend consumption plus the existing
buffer phase controller. Preserve the local and backend resampler paths
for providers without active feedback.

Keep audio diagnostics in the correct clock domains, report ring and
backend latency separately, and avoid hot-path feedback wakeups.
2026-08-10 04:44:55 +10:00
Geoffrey McRae
fa8a95569a [client] audio: preserve native playback formats 2026-08-10 03:57:03 +10:00
Geoffrey McRae
ff665c2031 [client] usb audio: support up to 192khz 24-bit
We can not support 32-bit because Windows is buggy:

The exact Windows 11 mmsys.cpl from build 26100.8737 populates Speaker
Setup testing against hard-coded speaker masks and for each calls
IKsFormatSupport::IsFormatSupported() using 24 hard-coded PCM formats.

These formats do not include 32-bit in 32-bit, consequently, every one
of the wizard’s format probes fails and it inserts zero channel-list
entries.

It does however test for 24-bit in 32-bit which passes, however this
exposes another breakage due to an inconsistency inside Windows
usbaudio2.sys

For bSubslotSize = 4, bBitResolution = 24, Windows does this:

1. It publishes a KS range whose minimum and maximum bit depths are both
   taken from bBitResolution, so the range says 24-bit.
2. It correctly constructs the actual stream format as:
   wBitsPerSample = 32, wValidBitsPerSample = 24
3. KS range intersection rejects that 24-in-32 format because its
   container is 32 bits while the published range says 24.
4. A packed 24-bit candidate passes range intersection, but the
   subsequent exact stream check rejects it because it uses a three-byte
   container while USB advertises four bytes.

Therefore no format can pass both checks. That exactly explains:

* USB Device Tree Viewer seeing 24-bit device ranges.
* The MMDevice endpoint exposing no usable formats.
* Windows being unable to start playback.

I verified this in the exact Windows 10.0.26100.8737 driver:

* KSPin::AddDataRange stores bBitResolution into both KS bit-depth
  bounds.
* MiniportWave::DataRangeIntersection tests those bounds.
* WaveFormatInfo::IsMatchingStreamFormat separately compares both the
  container width and valid-bit count.
2026-08-10 03:47:55 +10:00
Geoffrey McRae
a1da8c14f3 [client] usb audio: connect USB redirection
Add an opt-in USB audio fallback and connect the emulator to an
available PureSpice USBREDIR channel.

Keep transport-provided audio in priority and serialize USB parser
processing and teardown on the PureSpice thread.
2026-08-09 22:29:11 +10:00
Geoffrey McRae
06f111dc90 [client] usb audio: add audio provider
Adapt the emulated UAC2 playback stream to LG_AudioOps.

Preserve borrowed packet delivery, publish reconstructed timing, and
synchronize provider availability and attachment transitions.
2026-08-09 22:12:39 +10:00
Geoffrey McRae
6979b93da5 [client] usb audio: emulate UAC2 playback
Add a fixed-format USB Audio Class 2 playback device for the
client-side USB redirection bridge.

Advertise stereo 48 kHz IEEE float audio and handle enumeration,
configuration, alternate settings, clock requests, and isochronous data.
2026-08-09 21:30:20 +10:00