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.
This commit is contained in:
3AvisD committed 2026-10-22 14:56:03 -06:00
1 parent 521527eb21
commit 8de6bceeae
9 files changed
+231 -61

No files matched your search

+11 -6
View File
@@ -78,12 +78,17 @@ opts in to Hyprland-only recovery of a default-prefix Riot session with no
visible window; it is off by default. See [troubleshooting](TROUBLESHOOTING.md#riot-exits-and-league-reports-that-it-lost-its-connection)
for the observed failures, recovery guards and NSURLSession limitations.
`RCLOL_HIDE_CLIENT_IN_GAME=1` opts in to hiding the managed `LeagueClientUx`
and `Riot Client` X11 windows while a match runs, then showing them when the
game process ends. It keeps the client open and is mutually exclusive with
`RCLOL_CLOSE_CLIENT_IN_GAME=1` (close takes precedence). It is off by default,
requires X11/Xwayland, and does not patch client binaries, CEF or the game. See
[the troubleshooting measurement](TROUBLESHOOTING.md#keep-the-client-open-but-hide-it-during-a-match)
`RCLOL_CLIENT_IN_GAME_TRICKS=1` opts in to automatic client handling during a
match. It reads `lol-user-experience` from the installed client's
`LCULocalPreferences.yaml`: with `potatoModeEnabled: true`, it closes the client
UI when `closeLeagueClientDuringGame: true`, otherwise it hides the managed
`LeagueClientUx`/`Riot Client` X11 windows and restores them when the game
ends. With client optimizations disabled or preferences unreadable it does
nothing. The low-level `RCLOL_CLOSE_CLIENT_IN_GAME=1` and
`RCLOL_HIDE_CLIENT_IN_GAME=1` switches remain available when the automatic
switch is not set. The feature is off by default, requires X11/Xwayland, and
does not patch client binaries, CEF or the game. See
[the troubleshooting measurement](TROUBLESHOOTING.md#automatic-client-handling-during-a-match)
for the measured CPU effect and limitations.
`RCLOL_FILTER_HOST_ENV=1` opts in to removing host desktop-session variables before
+29 -27
View File
@@ -192,30 +192,39 @@ observation, without waiting for a match:
python3 tools/close-league-client-in-game.py --once --dry-run
```
### Keep the client open but hide it during a match
### Automatic client handling during a match
`LeagueClientUx` can consume a noticeable amount of CPU while the client stays
open during a match. An opt-in alternative to closing it hides the managed
client window instead:
A single opt-in switch reads the client's own preferences and chooses the mode:
```sh
RCLOL_HIDE_CLIENT_IN_GAME=1 ./scripts/run.sh
RCLOL_CLIENT_IN_GAME_TRICKS=1 ./scripts/run.sh
```
The launcher detects when a match starts, unmaps the `LeagueClientUx` and
`Riot Client` X11 windows, and maps them again when the game process ends. The
client is not closed, the League backend and Riot client keep running, and the
game window is never hidden. `RCLOL_CLOSE_CLIENT_IN_GAME=1` takes precedence
when both flags are set.
It reads `lol-user-experience` from the installed client's
`LCULocalPreferences.yaml`:
The helper is off by default and window-management only: it does not patch
client binaries, CEF, anti-cheat or DRM. It attributes the game to this prefix
through the loader's `__mldr_sockpath`, and fails closed when ownership, proc
state, environment or window information cannot be read. It requires an X11 or
Xwayland desktop; on a native Wayland window manager without Xwayland it cannot
find the windows.
| Client preference | Launcher action |
|---|---|
| `potatoModeEnabled: false` or unreadable | no client-in-game helper |
| `potatoModeEnabled: true`, `closeLeagueClientDuringGame: true` | close the client UI |
| `potatoModeEnabled: true`, `closeLeagueClientDuringGame: false` | hide the client windows |
On a CPU-bound host the effect appears after CEF has been hidden for a few
The hide path unmaps the `LeagueClientUx` and `Riot Client` X11 windows and maps
them again when the game process ends. The client is not closed, the League
backend and Riot client keep running, and the game window is never hidden. The
close path uses the UI-close helper described above.
The low-level `RCLOL_HIDE_CLIENT_IN_GAME=1` and
`RCLOL_CLOSE_CLIENT_IN_GAME=1` switches remain available when the automatic
switch is not set. All modes are off by default. The helpers are
window-management only: they do not patch client binaries, CEF, anti-cheat or
DRM. They attribute the game to this prefix through the loader's
`__mldr_sockpath`, and fail closed when ownership, proc state, environment or
window information cannot be read. The hide helper requires an X11 or Xwayland
desktop; on a native Wayland window manager without Xwayland it cannot find the
windows.
On a CPU-bound host the hide effect appears after CEF has been hidden for a few
seconds. In a local 30-second test on an i5-3470 with a Radeon RX 550, hiding
`LeagueClientUx` reduced the summed CPU of the matched client/CEF processes from
120.7% to 93.4% (about 23%, or 27 percentage points, of one core); showing the
@@ -224,16 +233,9 @@ a game that is GPU-bound, a client with no active UI work, or a different
desktop may show less benefit. The hidden window can also need a moment to
repaint after it is shown.
`RCLOL_CLOSE_CLIENT_IN_GAME=1` remains the more aggressive option when in-client
chat during the match is not needed. Configure one of the two, not both:
```sh
# Keep the client open, hide its windows while playing
RCLOL_HIDE_CLIENT_IN_GAME=1 ./scripts/run.sh
# Or close the client UI while playing
RCLOL_CLOSE_CLIENT_IN_GAME=1 ./scripts/run.sh
```
With client optimizations enabled and close-during-game enabled, the close
helper remains the more aggressive option when in-client chat during the match
is not needed.
Diagnose the match detector without changing any window: