Commit Graph
397 Commits
Author SHA1 Message Date
MaxsTechReview 8cf01ebb77 fix: Linux games on an NTFS USB drive start the first time instead of failing to load a library (#1850)
* fix: a read-only file on a USB drive no longer fails to close the first time it is read

On the RedMagic Astra 2, Android's NTFS USB drive returns EIO from close() for a file opened read-only when that first read updates its access time; the update itself succeeds and the descriptor is released. The x86 loader under FEX treats a failed close as fatal, so every Linux game newly installed or updated on such a drive failed to start once (libfreetype.so.6: cannot close file descriptor: Input/output error). The session library's close() now reports success for EIO on read-only descriptors; errors on descriptors opened for writing are still returned.

* Check the read-write close still reports EIO
2026-10-30 18:36:08 -04:00
MaxsTechReview 7bc3529722 fix(audio): DirectAudio no longer crackles where Android refuses low-latency output (#1862)
* fix(audio): DirectAudio no longer crackles where Android refuses low-latency output

On devices where Android won't give the game a low-latency output (AYN Thor,
Android 13), DirectAudio kept Wine's 10 ms period and 12 ms buffer. An
emulated game audio thread can't keep that pace there, so audio crackled.
The session now checks for low-latency output and, only when it is refused,
asks DirectAudio for a 20 ms period and a 60 ms buffer.

DirectAudio's settings are now AUDIO_DIRECT_* everywhere in DroidDeck and are
handed to the driver under the names it reads when DirectAudio is set up.
AUDIO_DIRECT_MS and AUDIO_DIRECT_PERIOD_MS can be set per game.

* fix(audio): game profile DirectAudio settings and the microphone-off setting reach the driver
2026-10-30 16:34:45 -04:00
MaxsTechReview 83980035c6 fix(desktop): video wallpapers no longer race ahead after DroidDeck returns from the background (#1833)
* fix(desktop): video wallpapers no longer race ahead after DroidDeck returns from the background

* test: give the vrclient loader harness the clock syscall hook
2026-10-30 13:58:49 -04:00
MaxsTechReview 8f7cdb7106 fix: Battle.net scales its windows to large desktops instead of opening tiny on high-resolution screens (#1832) 2026-10-30 13:58:44 -04:00
MaxsTechReview ab949a4a5a fix(runtime): the x86-64 Steam client starts again on the Ubuntu runtime (liblzo2-2 for FEX) (#1825)
* fix(runtime): ship liblzo2-2 so the x86-64 Steam client can install FEX

FEX's unsquashfs links liblzo2. The Ubuntu runtime did not ship it, so the FEX check failed on every build, the x86-64 client was never set up, and the session went straight back to the home screen. Only phones with the desktop installed had it.

* fix: the x86-64 Steam client starts again after it updates itself under FEX

On its first start the x86-64 client downloads a 500 MB update and, under FEX, ends on an illegal instruction (rc=132) instead of asking for a restart with rc=42, so the session ended there. The client is started again once.
2026-10-30 13:58:35 -04:00
MaxsTechReview d31f234f74 fix(xbox): games run from their own folder on the short drive, not the drive root (#1804)
* fix(xbox): keep the game in its own folder on the short drive instead of at the drive root

* fix(xbox): SD card Xbox games can read their own package files

Xodus mounts a store library on the selected SD card at /mnt/droiddeck-stores/<card> and links the launch view to it, but game sessions only bound that library as /mnt/droiddeck-sd. The links were dangling inside the game, so MicrosoftGame.Config, appxmanifest.xml and XCurl.dll could not be read and GDK games stopped with "Failed to initialize GDK". Game sessions now bind the same store roots Xodus uses.

* fix(xbox): give the SD Steam library its own store path when another store root shares the card

externalRootsForXodus added the selected Steam library's Games folder with the card's guest path even when another store root on the same card already used it, so both bound to one destination. It now takes a path-derived suffix in that case, the same way externalRoots separates its own roots.
2026-10-30 10:10:23 -04:00
MaxsTechReview f69e2d0171 fix: Steam's UI draws at an even share of the refresh near 60 fps instead of the panel's full rate (lag and heat since 0.6.7) (#1809) 2026-10-30 02:16:25 -04:00
MaxsTechReview 26e2f26ec9 fix: Steam's Browse buttons work when another app holds port 8080 with Decky enabled (#1798) 2026-10-29 21:22:14 -04:00
MaxsTechReview 23bb361006 fix: Steam no longer restarts every launch to import added games, and asks first (#1795) 2026-10-29 21:14:11 -04:00
MaxsTechReview ee3876b965 Windows components: restore bundle parts, wait for restores and keep older picks (#1788) 2026-10-29 20:31:18 -04:00
MaxsTechReview 31c943c82a fix: Windows installs to Android storage no longer ask for an administrator (#1791) 2026-10-29 19:12:22 -04:00
MaxsTechReview 161a93a4b3 Session follows the Android time zone, and Teardown keeps its own vsync (#1790) 2026-10-29 18:49:11 -04:00
MaxsTechReview b726e19fa4 Keep Windows components across runtime updates and reinstall lost ones (#1786) 2026-10-29 17:48:04 -04:00
MaxsTechReview 22d39998f0 fix(desktop): let desktop apps save read-only game files, and make game libraries writable (#1781) 2026-10-29 15:16:17 -04:00
MaxsTechReview 0258f10df0 fix(desktop): start Electron and Chromium apps from apt without the sandbox, on X11 (#1775) 2026-10-29 12:02:40 -04:00
MaxsTechReview 9f7f6d821d perf(epic): keep the hidden launcher from loading its store and Fab pages, and compress it while games run (#1764)
* perf(epic): keep the hidden launcher from loading its store and Fab pages, and compress it while games run

The hidden Epic Games Launcher that stays up for sign-in while a game runs pre-warmed its store and Fab pages on a display nobody sees. Under FEX each page used about one core and grew past a gigabyte, crashing and reloading in a loop. The hidden instance now skips the store pre-warm, gets a blank page in place of Fab, and is paged out to zRAM with the Steam client once a game has focus. The visible launcher is unchanged.

* test(zram): keep the scan fixture PIDs above the kernel PID range
2026-10-29 10:01:25 -04:00
MaxsTechReview 29c83976d0 Move the Linux runtime to Ubuntu 26.04 LTS with a separate Kubuntu desktop (#1733) 2026-10-29 09:05:20 -04:00
MaxsTechReview 283e3b4549 Use the second screen on dual-screen handhelds (#1734)
* Use the second screen on dual-screen handhelds

Detect built-in second screens such as the Retroid Pocket Duo and AYN Thor.
The sections move to a menu on the bottom screen, L2 and R2 switch sections,
and text fields type on the bottom screen so the top keeps the full view.
Sessions open the bottom-screen trackpad and keyboard when they start.
Setup gains a Dual screen choice (Automatic, On, Off) with toggles for the
bottom menu and the in-game controls. Closing the bottom menu no longer ends
a running session.

* Type into Steam from the bottom screen

While the bottom-screen trackpad and keyboard controls are open in a Steam
session, Steam's own on-screen keyboard no longer covers the top screen.
The agent keeps Steam's text target and asks the app instead, which opens
the Android keyboard on the bottom screen and hands focus back to the game
when it closes. Modal and VR keyboards, and sessions without the bottom
controls, keep Steam's keyboard. The Show keyboard button now follows the
keyboard when it is closed another way.

* Open the bottom controls after the first frame and tidy dual-screen translations

* Move the in-game menu to the bottom screen on dual-screen handhelds

Fix controller input and focus on the second screen: keys and sticks reach the game after touching the bottom controls, closing the bottom controls returns focus to the game, B closes bottom typing, and the typing panel keeps a focusable window until focus has left it.

* Let B close the open layer of the session menu first and focus the selected bottom-screen mode

* Let the Retroid Pocket Duo Home double press open its quick menu during sessions

* Open the keyboard on the bottom screen for Steam text fields and hide it on Enter or when the field loses focus

* Keep controller focus on the top screen when a section is picked on the bottom screen

* Keep LB and RB on the store tabs and let Back return from a store to its tab

* Show the Adreno 722 as supported on the Retroid Pocket Duo

* Label the Steam integration suggestion's close button Close and cover that closing it is permanent

* Close the docked menu with its presentation, keep a focus picked during the stop delay, and ignore panel picks on process-settings pages
2026-10-29 07:52:18 -04:00
MaxsTechReview e9e0186e66 perf(fex): answer raw stat, readlink and statx syscalls through the proot fast path (#1757)
* perf(fex): answer raw stat, readlink and statx syscalls through the proot fast path

FEX issues newfstatat, readlinkat and statx as raw syscall() calls, which skipped the libc wrappers the fast path hooks and fell through to ptrace. Route them through libblfastpath the same way raw openat already is, and keep the fast path's own /proc/self/exe lookup off the hooked syscall().

* test(fex): keep the raw lookup test passing on kernels without statx
2026-10-29 07:25:39 -04:00
The412Banner 110cfc28f8 feat: FusionHUD replaces the session HUD, with MangoHud's readings (#1743)
The session HUD is FusionHUD (Bannerlator's HUD) with every reading taken from
the same source, and worked out the same way, as the MangoHud build that runs
Steam's performance overlay in a DroidDeck session.

- gamescope patch 0125 (gamescope-3.16.29-p19) shares the frame times that
  mangoapp reads (one per signalled commit of connector 0) in a ring named by
  DROIDDECK_HUD_FRAMES; the app reads it once per display frame and counts the
  compositor's frames when gamescope sends none.
- MangoHud's rules: FPS over periods of at least 500 ms, frame time = 1000/FPS,
  200-frame graph on a fixed 0-50 ms scale; CPU, GPU, temperatures, RAM, swap,
  VRAM and battery from MangoHud's sources. Zones 22/26/28 are typed as GPU and
  DDR sensors, so Steam's overlay CPU temperature no longer includes them.
- Five sizes in a panel shaped like the DroidDeck mark, with a centred header,
  one left edge, neon outline and FPS; Minimal is the default size. Settings on
  a new "Performance HUD" drawer page, with Bannerlator's options.
- The HUD reads sensors and polls frames only while it is drawn (not while
  hidden, in picture-in-picture or behind another app), keeps its place after
  picture-in-picture, and the diagnostics export has its own reader.

Device-tested on the AYANEO Pocket FIT: same readings as Steam's overlay side
by side in Dead Cells; the HUD updates in a game, hides in picture-in-picture
and comes back in place, no crashes.
2026-10-29 01:53:45 +00:00
Kurt Himebauch 198f667bf0 feat: add GOG maintenance 2026-10-28 16:10:17 -04:00
Kurt Himebauch 52fa41767c fix: stop stale Android readbacks snapping Steam's brightness slider back (#1731)
* fix: stop stale Android readbacks snapping Steam's brightness slider back during a held stick

* fix: let deploy_fast sign with the release env on macOS and Linux

* fix: honor DROIDDECK_SIGNING_ENV first and cover the env signer in tests

* fix: honor DROIDDECK_SIGNING_ENV first and cover the env signer in tests

* fix: retry held brightness readbacks, use a monotonic hold clock and resolve the signing env path

* fix: resolve the build-tools path before signing changes directory

* fix: pick the newest build-tools numerically and keep the env file from replacing them

* fix: only pick build-tools that have aapt, zipalign and apksigner
2026-10-28 15:25:48 -04:00
The412Banner 9d82df6981 fix(game-env): OpenGL games stop waiting for each screen refresh (#1715)
With no frame limit, AIO's Direct3D 7 (DirectDraw) test ran at exactly
144 fps on a 144 Hz panel: every frame waited one refresh (6.94 ms).
Wine asks for a swap interval of 1 on every OpenGL window, and WineD3D's
front-buffer drawing used by DirectDraw and Direct3D 1-7 never lowers
it; it only sets the interval in its present path. Mesa's Zink then
presents in FIFO.

droiddeck-game-env sets vblank_mode=0 for games launched through Proton
before the game's environment edits, so a value set in the launch
options or the editor wins and an editor Remove leaves Mesa's default.
Steam's own runs in compatdata/0 are unchanged. Steam's Frame Limit
still holds a game: gamescope's WSI layer presents every swapchain in
FIFO while its limiter is on.

On the AYANEO Pocket FIT, AIO Direct3D 7 went from 144 to 2,345 and
2,265 fps (1 % low 99 -> 620) with no limit; with the Quick Access
limit at 144 and 72 it held at 143.76 and 71.92.
2026-10-28 13:34:45 +00:00
The412Banner 213c2da57e fix(steam): answer Steam's D3D driver query without starting Wine (#1708)
At every start, Steam's shader pre-caching runs d3ddriverquery64.exe
through each Proton tool (DroidDeck-Proton and the ARM64 Proton) in
compatdata/0. Here the query has never succeeded (948 of 948 runs in
the client's shader log failed, mostly exit code 1), and each run
started Wine in that prefix, where the two Protons upgraded it back and
forth (11.0-100 <-> GE-Proton11-11) with the 32-bit wine.inf install.
When that overlapped a game's start, AIO ran 25-30 % slower for its
first 5-7 seconds.

Both Proton wrappers now exit 1 for Steam's own query, "run
.../d3ddriverquery64.exe" (or the 32-bit name) with STEAM_COMPAT_DATA_PATH
in compatdata/0, before doing anything else, so Steam gets the same
failure without Wine. Every other verb and prefix goes on to Proton.
2026-10-28 09:21:49 +00:00
Kurt Himebauch 374d4783fc fix: avoid incompatible Turnip selection and explain Steam startup failures (#1380) 2026-10-27 22:29:40 -04:00
Kurt Himebauch eceda6e840 Add opt-in game debug logs and bounded log sharing (#1061) 2026-10-27 22:22:33 -04:00
The412Banner 4ef6b53eb0 fix(proton): Windows CPU 0 is the fastest core (#1697)
Wine numbers the Windows CPUs like the host, so Windows CPU 0 was host
core 0, a small core on most Android chips. Games that pin their main
thread to CPU 0 ran it there: GTA IV 32 fps on the AYANEO Pocket FIT,
61 fps once CPU 0 is the fastest core.

droiddeck-game-env hands Wine the game's cores fastest first, from each
core's cpu_capacity (or its top clock). Equal cores keep their order.
Cores picked globally or in a game profile stay the only cores the game
sees, now fastest first; a pick only counts when it narrows the cores.
Games on Proton's own default_cpu_limit list keep their count on the
fastest cores (quoted and unquoted counts); other values such as "P"
are left to Proton. A typed WINE_CPU_TOPOLOGY / PROTON_CPU_TOPOLOGY
still wins, an empty one turns it off for a game, and
DROIDDECK_FASTEST_CORES=0 turns it off. Steam's own Proton runs in
compatdata/0 are left as before.

Builds on maxjivi05's "Windows games see only the cores they are pinned
to" (9d85af75).
2026-10-27 19:07:59 -04:00
The412Banner 43a0ce93f9 fix: Frame Limit sync and refresh follow on a still screen (review follow-ups) (#1663)
The Steam helper checked the Frame Limit only when the offered frame
rates changed. With the limit off during a refresh change, turning it
back on left a value the new rate does not offer, and a failed write was
not tried again. It now checks on every state change and every 5 s, and
waits for Steam's settings write so a rejected write is caught and tried
again on the next check.

gamescope 3.16.29-p16 (0120 changed): gamescope took a new host refresh
only from the presentation feedback of a frame it drew, so with nothing
moving on screen it kept the old rate. It now presents once when the
host's wl_output mode changes and keeps presenting while a new rate is
pending, so the 300 ms check runs on a still screen too.

Found by CodeRabbit in the reviews of #1650 and #1663.
2026-10-27 05:08:21 -04:00
The412Banner 4c7e59ed8b feat: Steam's Frame Limit decides; gamescope and the limit follow the refresh rate (#1650)
Remove the Performance mode switch. The session always runs the way
Performance mode did: replaced buffers go back to the game at once
(except while mirroring to glasses), gamescope's WSI layer and winex11
reuse their per-present window checks, and games get eight swapchain
images while uncapped. Steam's Frame Limit in the Quick Access menu is
the only limit.

gamescope 3.16.29-p15 (p14 plus two patches):
- 0119: with the Frame Limit on, gamescope forces FIFO while the WSI
  layer hands the driver MAILBOX, so a game with eight images could
  queue up to seven frames ahead of the screen. While the limiter forces
  FIFO the layer uses its default of 3 images; DXVK and VKD3D-Proton
  recreate their swapchain when the limiter changes, other apps are asked
  to with VK_SUBOPTIMAL_KHR.
- 0120: -r fixed gamescope's pacing and limiter rate for the whole
  session. With GAMESCOPE_NESTED_REFRESH_FOLLOWS_HOST=1 a rate the host
  has reported for 300 ms replaces it (a switch from 144 to 120 Hz passes
  through 72 Hz for a few frames), and Steam gets the display information
  again. The session sets it whenever it passes -r.

Steam keeps its Frame Limit as the client setting
gamescope_app_target_framerate and offers the values gamescope's display
state lists. After a refresh change, a limit the new rate does not offer
(72 at 120 Hz) left the slider on its first value while the game kept the
old limit. The Steam helper watches the offered values and, once they
settle, keeps the limit when it is still offered and moves it to the
highest value otherwise, through Steam's own setting so the slider shows
it. Steam's webpack does not expose its module cache, so the gamescope
service is found by the calls its module makes, and the helper retries
the install every 10 s until Steam is ready.

The session window asks for the fastest mode the peak refresh setting
allows and chose again only when the display changed, so after it had
asked for 60 Hz, raising Android's refresh setting left the display,
gamescope and the limit at 60. It now also chooses again when
peak_refresh_rate or min_refresh_rate changes.
2026-10-26 23:17:35 -04:00
maxjivi05 bb9a64fa5f Reconfigure the app decoder when the capture layout changes
A capture format or buffer change now closes the app's decoder so the
next packet reopens it with the new stride and height, and a capture
slot whose remap fails no longer keeps its old mapping.
2026-10-26 20:36:24 -04:00
maxjivi05 916a39585f Decode Remote Play streams on the arm64 Steam client
Steam's arm64 streaming_client only decodes through a V4L2 stateful
decoder and libdrm dumb buffers, neither of which exist on Android, so
streams from a PC never showed a picture. The preload now offers it a
/dev/video-dec0 and a libdrm stand-in backed by dma-heap buffers, and
each frame is decoded by the app's MediaCodec (Qualcomm low-latency
mode) over the encoder socket, falling back to the FFmpeg in Steam's
runtime.
2026-10-26 20:36:24 -04:00
maxjivi05 9555cb9f65 fix(skate.): run ReSkate at D3D12 feature level 12_1
skate. under ReSkate crashed with an access violation in Skate.exe 12 to
60 seconds after it started at the default feature level 12_2; at 12_1
it loads San Vansterdam and plays. The rule matches Skate.exe with
ReSkate.dll beside it, so it covers ReSkate started from skate.'s own
Steam entry and as a non-Steam game, and a game profile can still set
another level.
2026-10-26 20:35:59 -04:00
maxjivi05 70d8fc6559 Hand a profile's WINE_CPU_TOPOLOGY to Proton as well 2026-10-26 18:31:11 -04:00
maxjivi05 70c512693a Set PROTON_CPU_TOPOLOGY too so Proton's per-game CPU list doesn't replace it
Proton sets WINE_CPU_TOPOLOGY from its own default_cpu_limit for games
like Prototype (8 cores) unless PROTON_CPU_TOPOLOGY is set, so the
pinned topology never reached the game the issue was about.
2026-10-26 18:31:11 -04:00
maxjivi05 43266b2923 Keep an empty WINE_CPU_TOPOLOGY from a game profile 2026-10-26 18:31:11 -04:00
maxjivi05 9d85af7558 fix(proton): Windows games see only the cores they are pinned to
Game cores pinned the game with taskset, but Wine counts the online
CPUs, so a game held to two cores still saw eight processors and sized
its thread pools for them. Prototype freezes at its splash screen that
way. When the session or a game profile limits the game cores, Wine now
gets WINE_CPU_TOPOLOGY for exactly those cores unless the profile sets
its own.
2026-10-26 18:31:11 -04:00
The412Banner 830c753312 fix: turn off D3DGear's capture hook when it sits beside a game (#1627)
The Crew 2 loads D3DGear64.dll from its folder. Its DXGI Present hook
faults over a thousand times within seconds under Wine and the game
never presents again: black screen while the sound keeps playing.
droiddeck-game-env now disables the DLL when it finds it beside the
game, and DLL overrides from several engine fixes are kept together
instead of the last one replacing the others.
2026-10-26 18:07:15 +00:00
Kurt Himebauch a0a68f7280 feat(steam): sync QAM controls and pass held Back shortcuts (#1621)
Steam's native QAM sliders now control Android brightness and media
volume, with device changes reflected back in Steam. Holding Android
Back for 700 ms sends a real held QAM button for Steam shortcuts. Single
and double taps keep the existing menu/QAM order and swap setting; the
double-tap window remains 500 ms.

- Discover native brightness through a guest backlight descriptor and
use Android's Modify system settings permission. Retain the latest
pending request until permission is granted or the session stops, with a
notification action for hidden sessions.
- Give DirectAudio and fallback AAudio sinks Android media volume/mute
callbacks, keeping software gain at unity. Recover when initial volume
state is absent or invalid, brightness acknowledgements differ or never
arrive, or the Display bridge is not ready yet.
- Forward other buttons while QAM is held in Steam Deck and Steam
Controller modes. Consume release after a hold and clear pending input
on overlays, focus loss, pause, disconnect, and teardown. The session
menu retains its compact Back choice without an explanatory paragraph.

Validation:
- Local ARM64 release build passed. The latest timing change passed 20
targeted input tests, including release at 600 ms remaining a tap. The
preceding full feature check passed 61 Android input/device-control
tests, with permission cases on API 28 and 33.
- 66 Linux Python/Node/C tests passed for device controls, audio
recovery, Steam compatibility, and file dialogs. Both audio sink modules
rebuilt with Android NDK 27.2.
- Release-signed integration build 14d12cf0 is installed on the unrooted
AYN Thor, carrying the Android/input changes through 749ade4a plus the
existing portrait changes. Device checks confirmed the configured
QAM/menu tap order, Back dismissal, removal of the inline menu
description, and held QAM overlapping X with clean release. Hands-on
testing confirmed this installed build works.
- Earlier Thor testing covered brightness permission and pending
requests, brightness synchronization in both directions, native volume
changes, hardware volume key readback, and both sink backends. Failure
recovery is covered by the automated tests above.

The subsequent queued-notification fix in 4d7ceb23 is covered by the
Linux regression suite and has not replaced the Thor install.

Bluetooth/wired output switching and other device models remain
untested. CI and CodeRabbit monitoring continue against the pushed head.
2026-10-26 13:46:14 -04:00
maxjivi05 455bf0fba9 fix(fex): install DroidDeck's FEX build again when it no longer loads
A tag that matches no longer vouches for the build: FEX and FEXServer must
also load (ld.so --list), otherwise the session reinstalls it and x86
programs use the Steam or system FEX meanwhile.
2026-10-26 13:40:36 -04:00
maxjivi05 4de4c65c2a fix: wait before retrying a FEX build that did not install
A failed catalog install is retried after an hour or when the session names
another build, a missing updater falls back to the FEX already here, and the
archive download gives up on a stalled connection.
2026-10-26 13:40:36 -04:00
maxjivi05 7e2d13b641 fix(fex): x86 programs use DroidDeck's own FEX build, kept to the catalog's version 2026-10-26 13:40:36 -04:00
maxjivi05 13493d44c3 fix: keep Sentry for Godot games that are not .NET
The Sentry GDExtension was turned off for every Godot game that ships it,
because its crash handler takes the .NET runtime down under FEX. GDScript
games such as Pathogenic call SentrySDK from their scripts, so without the
extension their autoloads fail to parse and the game quits. Only Godot .NET
builds have it turned off now.
2026-10-26 13:27:59 -04:00
Kurt Himebauch 4d7ceb2325 fix(steam): drain queued control notifications 2026-10-26 13:27:03 -04:00
maxjivi05 a984d11742 fix: run Xbox games from a short drive letter
The launch view lives under the app's files folder, so games saw an
install path like Z:\data\user\0\com.droiddeck.launcher\files\xbox-runtime
\views\launch-<n>\droiddeck-xbox-<id>. Forza Horizon checks that length and
quits with "Installation path is too long". The view is now mapped to a
free drive letter in the prefix (X: first) for the length of the launch.
2026-10-26 13:21:31 -04:00
Kurt Himebauch fa5506df35 fix(steam): preserve Back taps and recover QAM controls 2026-10-26 13:13:08 -04:00
maxjivi05 c446566f42 fix: hold a setup lock instead of guessing from running processes 2026-10-26 12:47:00 -04:00
maxjivi05 2e2b950964 fix: Flatpak setup clears a package lock left by an interrupted run 2026-10-26 12:47:00 -04:00
Kurt Himebauch 6a5dfe1486 feat(steam): sync QAM brightness and volume with Android 2026-10-26 12:32:36 -04:00
Kurt Himebauch d08afbd878 fix: restart compression delay for new games 2026-10-26 11:55:01 -04:00
Kurt Himebauch 36135327f5 fix: resolve zram focus conflicts 2026-10-26 11:45:17 -04:00