Commit Graph
118 Commits
Author SHA1 Message Date
MintMachineHQ 54f301a0e0 fix(tools): address review feedback on diagnostics
- doctor: resolve the workspace/Nix runtime before the native path, honour
  multi-entry XDG_DATA_DIRS, raise the kernel minimum to 5.14, and redact
  home/prefix/workspace paths by default (--no-redact opts out). Reports are
  written mode 0600.
- crash-report: drop the whole-process table from the default bundle
  (--all-processes opts in), mask credentials in argv, strip window titles,
  validate --label, find the workspace launcher log, bound the log tail,
  describe missing logs, write the archive 0600 without owner metadata, and
  keep --json output pure JSON.
- perf-baseline: reject non-finite times and absurd frame times, count
  --last by usable match, include the last sample interval in duration,
  record only the log basename, and rename p50/p95/p99 to sample_p* to make
  clear they are ten-second samples.
- docs: correct the metric descriptions, flag names and shader-cache sign.
2026-10-25 12:28:48 -06:00
MintMachineHQ 11f7252004 feat(tools): add host doctor, crash report and frame-pacing baseline
Turns "it does not work" into an attachable report instead of a log-less
issue. Three read-only host tools, reachable from the launcher:

- doctor.py checks GPU/driver, Vulkan ICDs, display session, memory, disk,
  overlay layer, core-dump limit, i915 panel self-refresh and prefix/runtime
  state. --json and --report produce an issue attachment; warnings do not fail.
- crash-report.py bundles the doctor checks, process table, dserver and
  launcher log tails, graphics kernel messages, display state and recent core
  dumps. Environment is never collected and home/user/host are redacted.
- perf-baseline.py parses the game's own netstats.csv into average FPS,
  p50/p95/p99 frame time, slowest-quarter FPS and hitch count, with --json and
  --append for before/after comparisons.

COMPATIBILITY.md records the verified UHD 620 row with measured numbers
(24-32 avg FPS, p99 44-98 ms) and explains how to submit another one.
2026-10-23 23:56:30 -06:00
lucannez64andClaude Opus 5.5 a11a144767 Merge main into fix/recover-stale-client
Resolve conflicts with #122: keep both feature docs and CI steps, and drop
this branch's copy of the close-helper block, which main now starts after
the installed-client check.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 14:18:33 +02:00
3AvisD 9194beef2f fix(launcher): harden stale-client recovery
- fail closed when X11 omits _NET_CLIENT_LIST or WM_CLASS, and recognize the
  RiotClientServices window class;
- require stale client processes to be at least 60 seconds old;
- recheck process identity before SIGTERM and SIGKILL and recheck the window
  before signalling;
- document the age and window-detection guards.
2026-10-23 06:08:45 -06:00
3AvisD f8bb14624e fix(launcher): address in-game helper review
- restore hidden windows even when the launcher output pipe is closed;
- exit the hide watcher after ten idle minutes and start it only after the
  installed-client check;
- reject missing, malformed or invalid close-during-game preferences instead
  of silently selecting hide;
- document the preference contract and idle behavior.
2026-10-23 06:08:45 -06:00
3AvisD 0a04d4e16c fix(launcher): remove orphaned client-in-game helpers
A launcher can exit while its long-lived close/hide helper remains. The next
run then starts another watcher, so several copies watch the same prefix.

Add an opt-in RCLOL_CLEAN_STALE_HELPERS=1 preflight that removes only helper
processes of this prefix reparented to init/systemd. Helpers of a live
launcher, other prefixes, the game, Riot/League/CEF, darlingserver and the
runtime are preserved. Unreadable or relative process data leaves a process
alone.

Validated across repeated launcher starts: the cleanup removed four, then one,
then one orphaned watcher; a subsequent dry run reported no orphaned helpers.
Zombie reaping after partial recovery is tracked separately in #124.
2026-10-22 15:50:38 -06:00
3AvisD 732e9c8881 fix(launcher): handle YAML comments and log failures
- strip inline YAML comments from preference values, including quoted values;
- keep a successfully unmapped window tracked when the success log raises
  BrokenPipeError, while still discarding a window whose unmap failed;
- cover both cases with tests.
2026-10-22 15:30:45 -06:00
3AvisD c8dd3886fc fix(launcher): recover a stale client tree without restarting Darling
Darlingserver normally stays alive after the Riot Client or game is closed.
If the client window disappears but Riot/League/CEF processes remain,
restarting via run.sh reuses a half-dead runtime and can fail to open a
window.

Add an opt-in RCLOL_RECOVER_STALE_CLIENT=1 preflight. When a darlingserver is
alive, no game is running, no managed client window is visible and stale
client processes belong to this prefix, stop only that client/CEF tree.
Preserve darlingserver, launchd/mldr, sockets and .init.pid, then continue
with the normal product launch.

The helper fails closed when X11 is unavailable, never touches a running game
or a visible client window, and does not patch client binaries, CEF or assets.
It saves the Darling bootstrap, but not Riot Client/CEF startup; a full runtime
restart remains the fallback if no window appears.
2026-10-22 15:27:33 -06:00
3AvisD 5a06f34725 fix(launcher): fail closed on automatic mode edge cases
- restrict preference reads to the lol-user-experience section;
- distinguish a failed close-preference read from a missing key;
- reject xprop's 'not found' text as a WM_CLASS value;
- track a window before unmap so an interrupting signal still restores it;
- report the tricks-mode opt-out in the hide helper's startup message;
- cover the new cases with preference, window and interruption tests.
2026-10-22 15:07:47 -06:00
3AvisD 4faa622336 feat(launcher): select client-in-game mode from preferences
Add RCLOL_CLIENT_IN_GAME_TRICKS=1 as the practical launcher switch. It reads
lol-user-experience from LCULocalPreferences.yaml:

- potatoModeEnabled false or unreadable: no action;
- closeLeagueClientDuringGame true: close the client UI;
- closeLeagueClientDuringGame false: hide the client windows.

The existing close and hide switches remain low-level options when the
automatic switch is not set. The hide helper accepts the master switch, and
the resolver plus preference cases are covered by tests and documentation.

The local .desktop entry was validated with the master switch; the installed
preferences select hide on this machine.
2026-10-22 14:56:03 -06:00
3AvisD 3c046252a7 fix(launcher): address hide-client review findings
- associate target windows with the selected prefix through the guest PID,
  X11 _NET_WM_PID, NSpid and the loader socket; fail closed when ownership is
  unknown;
- let --once run without either opt-in gate, matching the documented
  diagnostic;
- route SIGHUP through the restore handler;
- cache non-empty WM_CLASS results per window and prune stale entries;
- cover unreadable /proc, host PID mapping and prefix ownership in tests.
2026-10-22 12:32:03 -06:00
3AvisD 415aa7a949 feat(launcher): hide the League client UI while a match runs
Add an opt-in alternative to closing LeagueClientUx: hide the managed
LeagueClientUx and Riot Client X11 windows while the game process runs and
show them again when it exits. The client stays open; the game window is
never touched.

Detection is attributed to the launcher prefix through __mldr_sockpath and
fails closed when proc, ownership or window state is unreadable. The helper
requires X11/Xwayland, restores the window on end, signal or error, and is
mutually exclusive with RCLOL_CLOSE_CLIENT_IN_GAME=1.

Document the flag, compliance scope and limits. A local 30-second test on an
i5-3470/RX 550 reduced summed client/CEF CPU from 120.7% to 93.4%; this is a
CPU-bound-host measurement, not a universal FPS claim.

No client binaries, CEF, assets or anti-cheat are modified.
2026-10-22 12:15:35 -06:00
lucannez64 e00ee99522 fix(launcher): only remove launcher artifacts this project created
Match the legacy entry against this checkout's desktop-run.sh instead of any
desktop-run.sh, and delete the legacy icon files only after that entry or the
old artwork proves ownership.  Quote and escape Exec arguments as the Desktop
Entry specification requires, so a checkout path with reserved characters no
longer produces an invalid entry, and escape the Path value.

Use StartupWMClass=RiotClientServices in both entries: Darling derives WM_CLASS
from -[NSProcessInfo processName], the basename of argv[0], and the launcher
starts .../RiotClientServices.  "Riot Client" is only the bundle display name,
so the checkout entry never matched the window.  Both entries now share
Name/GenericName/Comment/Icon/Keywords/Categories and a test keeps them in
sync; Terminal stays different because the checkout entry logs to
build/desktop-launch.log while the packaged entry runs the session in a
terminal.

Also drop the stray top-level icon copies, handle dangling legacy symlinks,
name the icon for assistive technology, document the alias and menu entry, and
cover the helper with disposable-HOME tests.
2026-10-21 17:38:42 +02:00
3AvisD 0947a9f20d launcher: use a neutral Darling Launcher name and icon
Use a project-owned identity for the visible desktop entry while keeping the existing binary, package and window-matching identifiers working. The helper now copies the project's original icon instead of extracting one from the client, and the old game-named entry and icons it created are removed. Extend the packaging check to assert the neutral fields.
2026-10-20 23:49:39 -06:00
nbandlucannez64 0d8da88894 fix: preserve ambiguous guest processes during prefix cleanup (#111)
* fix: preserve ambiguous guest processes during prefix cleanup

* fix: warn only for matching runtime cleanup candidates

---------

Co-authored-by: lucannez64 <[email protected]>
2026-10-20 13:02:29 +02:00
nbandKalah 0a9a75e820 fix(appkit): add NSSavePanel tag-name compatibility (#112)
Co-authored-by: Kalah <[email protected]>
2026-10-20 12:24:10 +02:00
lucannez64 b4cdd19f1b Fix Mach-O analysis with no matching strings 2026-10-20 11:52:23 +02:00
3AvisD 54edf6fca1 patches, tools, docs: use neutral integrity-check wording and state the compatibility scope
The patch comments and the Mach-O strings filter named an anti-cheat product. Use neutral wording; the patches still differ only in comments. The platform-identity document now says the overrides are for compatibility, not a bypass of anti-cheat, telemetry, licensing or platform controls.
2026-10-19 22:47:59 -06:00
lucannez64 ff8a985057 Merge current main into the tested VSync and VRR fixes 2026-10-19 12:59:58 +02:00
lucannez64 6bfdfbcac7 Merge VSync and VRR fixes for combined testing 2026-10-19 12:15:09 +02:00
lucannez64andClaude Sonnet 5.5 d3adda86fa Openpanel probe: expand the tree to the subfolder before selecting, print selection diagnostics
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 09:33:30 +02:00
lucannez64andClaude Sonnet 5.5 66474a3c76 Fix openpanel probe: keep trigger note and panel alive across modal pools
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 09:28:34 +02:00
lucannez64andClaude Sonnet 5.5 70a2feec42 Add standalone NSOpenPanel Open/Cancel probe for issue #85
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 09:19:42 +02:00
Kalah 8fc7d4dff3 Merge branch 'main' into fix/cocoa-window-decorations 2026-10-19 07:40:37 +02:00
lucannez64 041591352e Present full-window Metal layers on the managed X11 surface for VRR 2026-10-19 07:35:16 +02:00
Kalah 6c9abce695 Merge branch 'main' into fix/overview-stuck-super 2026-10-19 07:13:28 +02:00
ekisu b6c70354b3 Recompile NSEvent in incremental AppKit runtime builds 2026-10-19 01:15:32 -03:00
ekisu 8f97990d03 Implement Cocoa local event monitors for native client dragging 2026-10-19 01:15:03 -03:00
ekisu 41da6d9e0a Fix X11 decorations for client-drawn Cocoa windows
Synchronize Motif decoration hints on style and titlebar-property changes, including native-window recreation and restoring ordinary WM decorations. Add a ten-case standalone Cocoa/X11 regression probe and document validation on KWin/Xwayland.
2026-10-18 21:06:22 -03:00
lucannez64 27553d8874 Fix Metal VSync propagation to window swap intervals 2026-10-19 01:10:03 +02:00
lucannez64 01fdb0f28f Merge remote-tracking branch 'origin/main' into fix/mic-input 2026-10-19 00:55:17 +02:00
lucannez64andClaude Opus 5.5 d2ec718c48 AUHAL: accept Vivox's playback format and trace recorded levels
The issue #75 trace shows recording now runs, but Vivox's playback unit
(mic test loopback, other players' voices) sets interleaved Float32 stereo
at 32 kHz on input scope element 0 and got -10868. Apply the relaxed rule
to both client sides (input scope element 0, output scope element 1); the
playback path already interleaves for the device and PulseAudio resamples.

AudioUnitRender(bus 1) now traces frames and peak level (no samples) so a
log shows whether the client pulls sound or silence. The input check also
sets Vivox's playback format and expects unsigned 16-bit to be refused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 00:41:10 +02:00
lucannez64andClaude Opus 5.5 d443e631c2 update.sh: replace the shared serial and UUID automatically
Older setups shipped serial C02ZL0GVMD6N and UUID
6F3B2A1E-8C4D-4E5F-9A7B-1D2C3E4F5A6B to every install. After installing,
update.sh now runs configure-darling-platform.py --replace-known-defaults,
which provisions the prefix only when its saved identity still has one of
those values. Other custom values (imported serials/UUIDs, model, board,
manufacturer, ROM, MLB) are kept; prefixes with no saved identity or only
custom values are not touched.

provision() also drops a standalone system-id or provisioning_UDID derived
from the shared UUID instead of keeping it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 00:17:22 +02:00
lucannez64andClaude Opus 5.5 f7be4a2f93 AUHAL: accept interleaved recording formats on element 1
Vivox sets interleaved Float32 stereo on output scope element 1 and
AUBase's canonical-only rule rejected it with -10868, so voice chat never
started recording (issue #75 trace: 20 attempts, all failing there).
A real AUHAL converts any linear PCM; element 1 now accepts native-endian
float32 or 8/16/32-bit integers in either layout, which PulseAudio records
and RenderBus copies. Playback (element 0) keeps the canonical rule.

The input check gains a Vivox-style run: interleaved stereo 44.1 kHz with
the device set on element 1.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 00:13:16 +02:00
lucannez64andClaude Opus 5.5 87484f0385 close-league-client-in-game: don't block closes right after boot
last_close started at 0.0 and the cooldown compares it with
time.monotonic(), which counts from boot. For the first 30 s of uptime
every close was refused as "in cooldown". That made the tests flaky on
freshly booted CI runners (seen on PR #76). Use None for "never closed".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:16:18 +02:00
lucannez64andClaude Opus 5.5 662b3d414f X11: take modifier masks from the server's modifier map
Right Alt (keycode 108) was hard-coded as Mod5/AltGr. On layouts where it
is Mod1, the swallowed-release reconcile accepted Mod1 as held but rebuilt
the state with Mod5, so the guest could see Option and Function together.
Read the per-key masks from XGetModifierMapping (refreshed on
MappingNotify) and use them everywhere; the old table is the fallback for
unmapped keys. The probe now checks Right Alt against whichever mask the
backend reports.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:13:07 +02:00
lucannez64andClaude Opus 5.5 92e1b5d5ab riot-audio-input-check: detect a synchronous access callback by thread
The handler read a flag the caller wrote without synchronization, and
inferred "called inside the request" from whether the call had returned,
which misfires when the handler runs on another thread first. Compare the
handler's thread with the caller's instead and keep the shared results
atomic.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:08:48 +02:00
lucannez64andClaude Opus 5.5 97c0e596bc X11: release modifiers whose release the compositor swallowed
GNOME's overview delivers the Super press to the game window, eats the
release and hands the keyboard back without a FocusOut. The backend kept
Command held, so every later key and click reached the game as a Command
shortcut until a real focus change reconciled it (issue #74).

Each key, button, motion and crossing event carries the server's modifier
state; release any modifier key we track as down whose modifier is missing
from it. Synthetic events from other clients are ignored.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:03:23 +02:00
lucannez64andClaude Opus 5.5 a65818a7f5 Pass microphone input through CoreAudio and AVFoundation
Voice chat (Vivox) saw no capture device and Chromium was told mic
access was denied. Fixes for issue #75:

- AVCaptureDevice: audio is Authorized when CoreAudio has a default
  input device; requestAccess answers asynchronously. Video stays Denied.
- PulseAudio input device reports 2 channels on input scope, 0 on output
  (was copied from the output device).
- PulseAudio input stream: real sample/host timestamps, one device
  buffer per IOProc call, holes as silence, IOProc errors no longer cork
  the stream, record buffer attrs sized to the device buffer.
- AUHAL: two elements per scope like macOS, non-blocking
  AudioUnitRender on bus 1 with planar support, device records in the
  bus 1 format, input-only units route CurrentDevice/BufferFrameSize to
  the input device, input start errors handled.
- New offline check tools/riot-audio-input-check.cpp.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 22:55:11 +02:00
Kalah 0b02889968 Merge pull request #72 from 3AvisD/fix/close-league-client-in-game
fix(launcher): close the League client UI while a match runs
2026-10-18 20:56:18 +02:00
lucannez64andClaude Opus 5.5 9f62aa3ce0 close-league-client-in-game: start the idle clock only after a client was seen
A long patch or login can keep the League client closed for more than ten
minutes after launch; the helper then left before the first match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 20:48:43 +02:00
3AvisD 72eb402cd4 fix(launcher): keep Mesa's shader cache on the host
Mesa derives its shader disk cache from $HOME. Inside the guest that is
/Users/<user>, which does not exist on the host filesystem, so Mesa could not
create the cache and disabled it, once per process:

    Failed to create /Users/<user> for shader cache (Permission denied)---disabling

One launcher log contained 212 of those lines, and no shader compiled by one
process was reused by another process or by the next start: the client and the
game recompiled every shader on every launch, spending CPU at startup for no
gain.

Mesa is host code loaded into the guest and reads MESA_SHADER_CACHE_DIR verbatim,
so point it at a host directory; Mesa creates mesa_shader_cache/ (client and game
shaders) and radv_builtin_shaders/ below it. A non-empty value from the caller is
preserved, and a directory that cannot be created leaves the previous behaviour
instead of ending the launch.

Observed on a Radeon RX 550 with radv: no shader-cache failure after the change,
and 434 files / 5.6 MB written during one client start, still growing while the
client ran. The cache is reused from the second start on, which lowers the
client's CPU use while it starts; the startup-time gain itself has not been
measured separately.
2026-10-18 12:18:33 -06:00
3AvisD 823fa6addc fix(launcher): close the League client UI while a match runs
The client does not come back properly after a match when its own "Close client
during game" option is enabled. The UI (LeagueClientUx and its helpers) is a
Chromium/CEF instance and, under Darling, the pre-match instance keeps running:
the client the backend starts when the match ends is a second CEF instance on the
same --user-data-dir, and its window never paints. Its DOM and audio work and the
window stays black; closing the client by hand during a match leaves the same
state for the same reason.

RCLOL_CLOSE_CLIENT_IN_GAME=1 opts in to closing that UI from the host, and only
while a match runs, so the client that appears afterwards is the only instance.
The UI also competes with the game for CPU: on a four-core host with a Radeon
RX 550 a practice match reported roughly 120 FPS with the UI running and roughly
180 FPS with it closed. This is not the helper-killing memory optimization the
RAM section warns against, and the Riot client, the League backend and the game
are never touched.

The helper fails closed. It attributes the game and the client to the launcher's
prefix through the loader's __mldr_sockpath, since guest processes do not carry
DPREFIX (checked on a live session). It never closes a client younger than 60
seconds (the one the backend starts after a match), preserves a process of
another installation or owner, acts only when the environment and the stat fields
can be read, gives up after three closes in one match, and leaves after ten
minutes without a client or a match. It is off by default.

Tests use fake /proc entries and mock every signal.
2026-10-18 12:18:33 -06:00
lucannez64andClaude Sonnet 5.5 7ef148c76e Add standalone X11 drag-and-drop check for PR #63
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-18 18:59:43 +02:00
lucannez64 b53b963997 Merge remote-tracking branch 'origin/main' into pr61/system-profiler-overview
# Conflicts:
#	.github/workflows/source-check.yml
2026-10-18 17:32:11 +02:00
lucannez64 fd0d01e813 Merge remote-tracking branch 'origin/main' into pr61/metal-device-fixes
# Conflicts:
#	.github/workflows/source-check.yml
2026-10-18 17:31:14 +02:00
lucannez64andClaude Opus 5.5 29e35b6a93 Report the MacBookPro16,1 GPU name for Riot on AMD and Intel hosts
With DARLING_METAL_MAC_GPU_NAME=1, MTLDevice.name is the GPU the
MacBookPro16,1 that IOKit reports shipped with, from the host's vendor:
"AMD Radeon Pro 5500M" (vendor 0x1002) or "Intel UHD Graphics 630"
(0x8086). NVIDIA keeps its own name so the game never takes another
vendor's driver paths. recommendedMaxWorkingSetSize and every other value
stay the host's, which was the risky part of #61's identity.

The Riot launcher turns it on by default (0 or empty turns it off); other
Darling apps keep the host name. DARLING_METAL_GPU_NAME still wins.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 17:24:49 +02:00
beb64a4271 Report hardware and software overviews from IOKit and sysctl in system_profiler
system_profiler now answers SPHardwareDataType and SPSoftwareDataType (and
lists them in -listDataTypes). Model, serial number, platform UUID and
provisioning UDID come from IOKit's IOPlatformExpertDevice via ioreg; CPU,
cache and memory from sysctl; the OS version from sw_vers and uname. A
field the guest does not provide is left out.

#61 instead read a separate darling-smbios.conf written by a new
generator (gen-darling-smbios.py), with hardcoded fallbacks (an Intel Core
i9, macOS 14.7, SIP enabled). iokitd reads darling-platform.plist, so
system_profiler and IOKit could report different serials and models on the
same prefix, and the generator overwrote identities imported with
configure-darling-platform.py. Reading the guest's own APIs keeps a single
source of truth: configure-darling-platform.py remains the only way to set
or provision an identity, and it is still never run by install or launch.

tests/test_system_profiler.py runs the script under sh with stub guest
commands and runs in CI.

Split from #61.

Co-authored-by: DevWebeloper <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 17:17:05 +02:00
e66bd9a394 Fix Metal device edge cases; keep reporting the host GPU
From #61, without the default "AMD Radeon Pro 5500M" / 4 GB identity: the
host GPU's name and Vulkan working set stay the default for every app, and
the existing DARLING_METAL_GPU_NAME and DARLING_METAL_VRAM_MB overrides
remain the opt-in. Reporting 4 GB on a 2 GB card invites allocation
failures, and under-reports larger cards.

Kept from #61:
- registryID returns MTLDeviceInfo::kDefaultRegistryID instead of 0; a
  real Mac never reports 0 and apps key devices by it.
- Vertex buffer layout and attribute arrays release the old item after
  retiring it; the retire step read the item after the release could free it.
- newDepthStencilState, newSamplerState and the device name return nil (or
  the fallback name) when Indium throws, instead of unwinding through
  Objective-C.
- MTLDepthStencilGetIndium is declared only with DARLING_METAL_ENABLED.
- The replaceRegion trace probes at most `width` bytes, which stays inside
  the first row for every pixel format.

metal.patch is regenerated in its existing file order, so the diff is
these changes only. tests/test_metal_device_info.py compiles the host
check against MTLDeviceInfo.h as shipped in the patch and runs in CI.

Split from #61.

Co-authored-by: DevWebeloper <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 17:14:47 +02:00
41b5b6fc0f Add an opt-in filter for host desktop-session variables
RCLOL_FILTER_HOST_ENV=1 makes exec-guest.py drop host session metadata
(WAYLAND_DISPLAY, XDG_SESSION_*, XDG_CURRENT_DESKTOP, GNOME/KDE/GDM,
systemd, SSH agent, terminal, toolkit, Flatpak/Snap/AppImage, exported
shell functions) and set SHELL to the guest's /bin/zsh. It is off by
default; RCLOL_KEEP_HOST_ENV lists names to keep anyway.

Unlike the denylist in #61, the filter runs after the launcher sets its
GPU tuning, keeps everything Darling and the host graphics and audio
libraries read (DISPLAY, XAUTHORITY, XDG_RUNTIME_DIR and the XDG base
directories, D-Bus, PulseAudio/PipeWire/ALSA, DRI_PRIME, MESA_*, __GL_*,
__NV_*, VK_*, LD_PRELOAD for gamemoderun, LD_LIBRARY_PATH), and lives in
one place instead of three.

tests/test_exec_guest.py runs in CI; the launcher check also verifies
that MESA_NO_ERROR=1 and __GL_THREADED_OPTIMIZATIONS=0 reach the guest
with the filter on.

Split from #61.

Co-authored-by: DevWebeloper <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 17:13:24 +02:00