* Add VITURE glasses support: hardware control, 3D, head tracking
Glasses get their own controller over the MCU (permission, 120 Hz default, brightness, volume, sunblock, 2D/3D) and the game moves onto them when plugged in. The IMU drives Cardboard head tracking and the SteamVR driver. 3D falls back to one eye's view on phones that can't send the 3840x1080 signal. Options open from a glasses button in game and on the Steam page.
* Drop the glasses settings like Steam's: Play-style button, Settings lip, tabs
* Hang the glasses Settings lip over the top of the button
* Space glasses MCU commands so the IMU rate sticks, fit fixed resolutions to the glasses
* Keep Steam alive with SteamVR registered, run SteamVR at the glasses' rate, keep the glasses lip on top
* Fit VR games on the glasses: full view, seated origin at the head, pad hands reach with the d-pad
* Let the pad hands reach a metre out so buttons with deep colliders press
* Show every VR frame in order at 120 fps: wait for SteamVR's GPU work, present only finished copies, skip the grace on idle shared counters
* Glasses: SteamVR starts and stops with them, closer view with a field of view setting, Recenter on the pad
* Glasses: SteamVR field of view defaults to 90°
* VR pad hands: sticks move and aim the hands, left stick click switches the sticks to the game, d-pad pulls a held hand
* Glasses: Play SteamVR beside the glasses button instead of starting SteamVR with them, pad hands drawn as Index controllers and off while other VR controllers are connected, glasses sheet tabs sized like Steam's
* Track glasses mode, refresh-aware glasses window, align Play SteamVR with Play Steam
* Fix 3D on the glasses: full-res SteamVR presenter, revert VR 3D at session end, coalesce vsync ticks, no session restart after end
* Address review: glasses output after installs and session end, VR revert retry, display fallback, presenter swapchain retry, agent hex checks, drawer bumpers, glasses translations, docs
* Harden VITURE stereo negotiation and output refresh tracking
* Localize stereo recovery feedback and record Astra reconnect tests
* Improve test failure diagnostics and refresh Astra firmware findings
* Handle VITURE docks separately and reject truncated USB frames
* Glasses: remember a 3D fallback per model, docks as display only, VR timing fixes
- A 3D attempt that ends at the 640x480 fallback is remembered for that glasses
model, so Play SteamVR no longer blacks out the glasses after every restart;
Retry clears it and "3D for VR games" stays reachable
- A VITURE Mobile Dock on its own no longer counts as glasses; through a dock
Play SteamVR is hidden and the sheet shows the output and why there is no control
- HDR is probed on the glasses when the session starts there
- Glasses frames with a mismatched checksum are marked in the status frame log
- SteamVR layer and driver vblank counters stay monotonic across refresh changes;
one-eye render scale applies from activation and on mono/3D switches
- Compositor binds announce the refresh clients were last told; the presenter
retries a failed first swapchain
- Dead strings and helpers removed; docs updated
* Glasses: drop USB frames with a bad checksum
* Glasses: count frames dropped for a bad checksum
* Feat/viture xr (#907)
* Add RayNeo Air and GT support to the XR glasses pipeline
* Add RayNeo Air and GT support to the XR glasses pipeline
* Checkpoint glasses tracking, calibration, and SteamVR launch integration
* Checkpoint glasses tracking, calibration, and SteamVR launch integration
* Add XREAL 1S support and correct GT and Pro 2 tracking
* Add XREAL 1S support and correct GT and Pro 2 tracking
* Fix mirrored glasses tracking and recover SteamVR after device loss
* Fix mirrored glasses tracking and recover SteamVR after device loss
* Document confirmed XREAL 1S brightness control
* Document confirmed XREAL 1S brightness control
* Fix SteamVR glasses defaults and rendering controls
* Fix SteamVR glasses defaults and rendering controls
* chore: keep only the 3 newest session log folders (#852)
* chore: add agent comment rules (#748)
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
* Fix SteamVR polling, VITURE checksums, and fence tracking
Keep manual SteamVR launches polled, discard corrupt VITURE packets, and retire Vulkan fences out of order without blocking submissions at a fixed capacity. Preserve the contiguous completion watermark used by the presenter.
Fix optional Windows launcher configuration and audited helper staging. Add Android, Windows, and native tracker regression coverage.
* Fix SteamVR polling, VITURE checksums, and fence tracking
Keep manual SteamVR launches polled, discard corrupt VITURE packets, and retire Vulkan fences out of order without blocking submissions at a fixed capacity. Preserve the contiguous completion watermark used by the presenter.
Fix optional Windows launcher configuration and audited helper staging. Add Android, Windows, and native tracker regression coverage.
* fix: wireless ADB page names the child-process switch the way Android shows it (#848)
* l10n: refresh stale and untranslated strings in es, fr, ko, ru (#850)
* l10n: refresh stale and untranslated strings in es, fr, ko, ru
- mode_added_art_hint: now mentions Steam then SteamGridDB (all four locales).
- wincomp_needs_installer / wincomp_installers_note: es and ko still described
the old "coming soon" behaviour; align with the current English text.
- summary_remove_game: was still English in all four locales.
Machine-assisted translation; native-speaker review is welcome.
* l10n(es): say registro, not grabación, for the missing installer record
---------
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
* fix: a failed cloud save recovery no longer ends the app (#846)
The cloud-recovery thread started at every app start had nothing to
catch an error, so one went to CrashHandler, which halts the process
with status 2. In unit tests the thread can outlive the test that
started it, fail on the torn-down preferences, and take the whole test
run down. The error is now logged and the thread ends.
Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com>
* fix: an interrupted Linux runtime download resumes instead of starting again (#847)
* fix: an interrupted Linux runtime download resumes instead of starting again
installOnce() asked the downloader to resume but always deleted the archive in its finally block, so the next attempt began at zero. The archive is now named after the release version and checksum, a failed download keeps what it fetched, and archives of other releases (and the old fixed name) are removed. A checksum or extraction failure still deletes the file.
* test: Downloader resumes a cut-off download from the bytes it kept
Starts a socket server that promises the whole file, hangs up part way and then answers a Range request, and checks that the second downloadFile call resumes with the right offset and ends with identical bytes.
* fix: a resumed download discards a 206 that does not start where the kept bytes end
Downloader appended every 206 response to the partial file without
looking at Content-Range. A server or proxy that answers a Range request
with a different offset would leave a corrupt file. Check that the range
starts at the kept length; otherwise delete the partial file and start
again without a Range header.
Adds a test with a server that answers the Range request from offset 0.
---------
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
* l10n: German, French, Spanish, Italian, Portuguese and Russian for the zRAM, reset-settings and store free-space strings (#849)
* l10n: German, French, Spanish, Italian, Portuguese and Russian for the zRAM, reset-settings and store free-space strings
Adds the strings values-de, values-it and values-pt were missing (14 each) and the six that values-fr, values-es and values-ru were missing. Machine-assisted drafts that follow each file's existing register and terms; native review is welcome.
* l10n: correct missing active swap translations
---------
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* fix: droiddeckctl reaches variant-package builds (recover #842) (#854)
fix: droiddeckctl reaches builds shipped under a variant package
The provider authority and the start Activity's component were fixed to
com.droiddeck.launcher, so droiddeckctl could not talk to the antutu,
ludashi or pubg builds from tools/release/variants.txt. DROIDDECK_PACKAGE
now picks the package; the Activity's class name stays the same in every
variant.
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
* feat: droiddeckctl reports on-screen pacing (recover #843) (#855)
feat: droiddeckctl pacing reports the frames that reached the screen
Reads SurfaceFlinger's timestats for the game's layer (or the session's
SurfaceView) over a capture: frames on screen, fps on screen, the
present-to-present histogram and how many intervals were off the usual
cadence. Records split by a refresh-rate change are summed. A game's own fps
counter counts frames handed over, so it can't show dropped or doubled frames.
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
* fix: Steam can restart more than twice in a session (#754)
* fix: Steam can restart more than twice in a session
Every exit 42 counted toward the cap that stops an update which will
not install, and the count was never cleared, so the third restart of
a session ended it however far apart they were. A client that ran for
a minute before asking is not that loop: the count starts again.
* fix: measure the client's run time as it exits
The time spent collecting logs and checking FEX after the client exits
counted toward its run, so a slow cleanup could make a quick exit 42
look like a long one and clear the count.
---------
Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
* fix: the front end keeps its page when the Fold is folded or unfolded (#832)
* fix: the front end keeps its page when the Fold is folded or unfolded
MainActivity, FileManagerActivity, FilePickerActivity and StoreLoginActivity did not declare the screen-size configuration changes, so folding or unfolding a foldable recreated them and dropped their in-memory state. They now handle orientation, screenSize, screenLayout, smallestScreenSize and density themselves, like SessionActivity already does. uiMode is left out on purpose.
* fix: store login keeps rebuilding its toolbar when the display density changes
StoreLoginActivity builds its toolbar in code with dp-to-pixel values taken at creation time and has no onConfigurationChanged. It no longer declares density in configChanges, so a density change recreates it as before this PR. Size and layout changes are still handled in place.
---------
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
* Release pointer buttons without replaying stale motion (#803)
* Fix cursor warping on native touch down
* Preserve input cleanup without replaying stale pointer motion
---------
Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com>
* l10n: translate the strings added since #284 into zh-CN, zh-HK, zh-TW and ja (#539)
* l10n: translate the 184 strings added since #284 (zh-CN/HK/TW, ja)
The stores, cloud saves, Windows components, Steam touch, desktop
removal and background-downloads strings landed after #284's
translation snapshot, so every one of them fell back to English.
Translate all 184 into Simplified Chinese, Traditional Chinese
(Taiwan and Hong Kong) and Japanese, keeping each locale file's own
vocabulary (工作階段/會話, 解除安裝/卸載, 元件/組件, 設定).
Also fix four Hong Kong strings that kept the simplified 着色器.
* l10n(zh): fix stale and ambiguous strings found in review
Severe: summary_remove_game was untranslated English in all three
files; mode_added_art_hint, wincomp_installers_note and
wincomp_needs_installer still described the pre-#480/#492 English.
Also: distinguish the Setup wizard from Android system settings in
zh-HK/zh-TW (初始設定 / 系統設定 / Android 設定), unify library as
收藏庫, component as 組件 in zh-HK, session as 會話 in zh-HK, account
as 帳戶 in zh-HK, Trending as 趋势/趨勢, Forget as 清除, reword the
re-applied-at-launch, action-failed and already-in-Games strings, and
play as 執行/開啟遊戲 in zh-TW/zh-HK.
* l10n(ja): fix stale and ambiguous strings found in review
---------
Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* Rebuild and verify Windows VR runtime components
* Rebuild and verify Windows VR runtime components
* Add top, bottom, and centered picture positions for Steam sessions (#871)
* fix: dependency scan ignores folders above the game folder (#859)
* DroidDeck-Proton: get releases from the Droid-Deck org repo
DroidDeck-Proton is now built and released on Droid-Deck/DroidDeck-Proton
(11-9.1 is Latest there), so the Components page, the update check and the
guest installer read releases from the org repo instead of The412Banner's.
* feat: low-latency controller and touch toggles in the session drawer (#808)
* fix: SteamGridDB lookups no longer stick as "no match" after a failure; add a search to the art chooser (#876)
* feat: Steam home wall fills from the signed-in library instead of store picks (#878)
* test: cover GPU family and support classification (#880)
* Fix local builds on Linux failing after the first Comet build (#866)
* feat: sort the store library and installed tabs, and switch between card and list views (#798)
* feat: three-finger tap toggles Steam's on-screen keyboard in game mode (#782)
* fix: keep Quest-patched Turnip as the auto default (#853)
* Fix deploy_local.sh and droiddeckctl not finding a phone connected over wireless debugging (#864)
* fix: keep proot sessions alive when the kernel loses fork events (#457)
* fix(quest): correct desktop and Steam display corruption across sessions (#733)
fix(quest): stabilize desktop and Steam layer presentation
Keep Quest SDR scenes and the black backdrop off the Android Vulkan swapchain regardless of session order or HDR preferences. Only report the first frame after client content is submitted.
Add backdrop lifecycle and first-frame regression coverage. Record the user's successful Quest 3 Test 2 result.
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* fix: keep SteamVR syscall hooks and report Steam crashes (#905)
* fix: preserve SteamVR syscall hooks
* fix: report Steam crashes through gamescope
* fix: honor glasses pacing and resolution in SteamVR launches
---------
Co-authored-by: connor g <connorsspam1992@gmail.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Co-authored-by: Yassine Gherbi <y.gherbi.dev@gmail.com>
Co-authored-by: Resul Övür <92828257+ovurrsl@users.noreply.github.com>
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: Kirk <kirtoy.junsay@gmail.com>
Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
Co-authored-by: asdf17128 <asdf17128@gmail.com>
Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com>
Co-authored-by: Dantalian <wsu091227@qq.com>
Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com>
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
Co-authored-by: The412Banner <205237651+The412Banner@users.noreply.github.com>
Co-authored-by: FX1922 <120828496+FX192@users.noreply.github.com>
Co-authored-by: Muaz Kadan <32595066+muazkadan@users.noreply.github.com>
Co-authored-by: kingokksa <47888451+kingokksa@users.noreply.github.com>
Co-authored-by: Jamie Schenker <jam1esch3nk3r@gmail.com>
Co-authored-by: Jagger15 <jagger2333@live.com>
* Glasses: keep a pending 2D restore and the SteamVR recovery offer, show Play SteamVR only with a picture
* Translate the glasses calibration, XREAL and SteamVR recovery strings
* SteamVR recovery: give a finished teardown time to collect logs before restarting
* Credit the projects the XR glasses support builds on
* Joy-Cons: SteamVR hands from their gyro while SteamVR runs, one combined pad otherwise
* Headsets: settings badge on Play SteamVR instead of a top-right button, both shown only once connected
* Hand tracking: camera-tracked Joy-Cons and bare hands in SteamVR, drawn as white gloves
- Joy-Con movement from the accelerometer (report reordering, per-Joy-Con calibration, zero-velocity updates)
- MediaPipe pose and hand landmarks from the device camera, placement check, per-hand Kalman filter with the Joy-Con
- No controller connected: bare camera hands with Quest-style gestures, 1€ filtered, rendered as a white glove model built from a distance field
- SteamVR safe mode cleared before each start so one crash no longer blocks the driver
---------
Co-authored-by: MaxsTechReview <6025299+maxjivi05@users.noreply.github.com>
Co-authored-by: informalTechCode <informaltechyt@gmail.com>
Co-authored-by: connor g <connorsspam1992@gmail.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Co-authored-by: Yassine Gherbi <y.gherbi.dev@gmail.com>
Co-authored-by: Resul Övür <92828257+ovurrsl@users.noreply.github.com>
Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: Kirk <kirtoy.junsay@gmail.com>
Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
Co-authored-by: asdf17128 <asdf17128@gmail.com>
Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com>
Co-authored-by: Dantalian <wsu091227@qq.com>
Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com>
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
Co-authored-by: The412Banner <205237651+The412Banner@users.noreply.github.com>
Co-authored-by: FX1922 <120828496+FX192@users.noreply.github.com>
Co-authored-by: Muaz Kadan <32595066+muazkadan@users.noreply.github.com>
Co-authored-by: kingokksa <47888451+kingokksa@users.noreply.github.com>
Co-authored-by: Jamie Schenker <jam1esch3nk3r@gmail.com>
Co-authored-by: Jagger15 <jagger2333@live.com>
* Add an Adjust logo screen to move and resize a game's logo in Steam
* Report a failed write of the local logo position instead of throwing
* Record a Steam-side logo position change only once it has been taken over here
fix(quest): stabilize desktop and Steam layer presentation
Keep Quest SDR scenes and the black backdrop off the Android Vulkan swapchain regardless of session order or HDR preferences. Only report the first frame after client content is submitted.
Add backdrop lifecycle and first-frame regression coverage. Record the user's successful Quest 3 Test 2 result.
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
feat: droiddeckctl pacing reports the frames that reached the screen
Reads SurfaceFlinger's timestats for the game's layer (or the session's
SurfaceView) over a capture: frames on screen, fps on screen, the
present-to-present histogram and how many intervals were off the usual
cadence. Records split by a refresh-rate change are summed. A game's own fps
counter counts frames handed over, so it can't show dropped or doubled frames.
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
fix: droiddeckctl reaches builds shipped under a variant package
The provider authority and the start Activity's component were fixed to
com.droiddeck.launcher, so droiddeckctl could not talk to the antutu,
ludashi or pubg builds from tools/release/variants.txt. DROIDDECK_PACKAGE
now picks the package; the Activity's class name stays the same in every
variant.
Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com>
A failed token refresh returned the stored access token even after it had expired, so the next request failed with a generic error instead of asking to sign in again. The stored token is now returned only while it is still valid.
The Epic docs now say that achievements are sent with Epic's launcher user agent, which the achievements service requires.
Both store modules are rewritten from a protocol-level spec: new Rust engines behind a small JNI surface (nativeCall/nativeInstall) and thin Kotlin facades, with the launcher's own user agent.
Epic: sign-in carries over, library, manifest download with byte-exact verification, assembly, uninstall, launch arguments, achievements.
Amazon: sign-in carries over, library, manifest download with per-file hash checks, path checks, executable detection from fuel.json, uninstall.
On-disk install layout is unchanged, so existing installs keep working.
Store game pages now take controller focus on their lead hero action (Install, Uninstall, Pause, Resume, Get, Buy), fall back to Back, and keep D-pad focus inside the page while it covers the library.
Space checks before Epic, GOG and Amazon installs (measured zero vs unknown), clear failure reasons with retry/clear, resume-aware checks, and safe per-file replacement so a failed or cancelled update never breaks an installed game.
Epic installs stream chunks straight into staged files in parallel (most bytes written once, a small budgeted cache for shared chunks, about 1x game size instead of 2x), pace updates by free space, and keep the lookahead, batch and bounded Java writers as hidden alternatives.
Co-authored-by: Juan Marti Mercado <juanma@microsoft.com>
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
* feat: add Cardboard mode with side-by-side lens-distorted eyes and 3DoF head tracking
* fix: derive the Cardboard field of view from the panel and recentre fully when far from upright
* feat: share the Cardboard head pose with the guest and add a SteamVR driver for it
* feat: run SteamVR's compositor on Turnip/KGSL with a display-extension layer and a driver-direct HMD
* feat: show SteamVR frames in Cardboard mode through a driver-side presenter and a fake direct-mode display
* feat: install and start SteamVR for Cardboard mode from the session drawer
* docs: describe Cardboard mode and the SteamVR path
* feat: drive SteamVR hands from the game pad and keep the Cardboard headset out of standby
* docs: record where the SteamVR dashboard stops
* fix: map Cardboard head tracking to the screen's axes and keep turns about the real vertical as yaw
* fix: give Cardboard its previous picture back when SteamVR stops
* fix: report sem_otime from emulated SysV semaphores so SteamVR's web helper can start
* fix: bridge SteamVR's shared semaphores across processes and keep Steam alive while SteamVR runs
* feat: present SteamVR straight to DroidDeck's compositor at panel resolution
* docs: update Cardboard VR notes for the dashboard, semaphore bridge and direct presenter
* fix: keep Wine and FEX signal handlers in the VR layer; add semaphore tracing
* fix: clear a stale SteamVR active marker on status
* fix: clear only an old SteamVR active marker
* fix: unblock SteamVR clients on Turnip and keep Steam's web helper alive across SteamVR runs
* fix: judge shared waits before a submit's own signals and on Vulkan 1.0 devices
* docs: record VR games, SteamVR Home and OpenXR results on the Thor
* docs: add Cardboard VR learnings from the Thor bring-up
* docs: add Cardboard VR screenshots from the Thor
* fix: keep the VR layer's display stand-in to SteamVR runs and clear a leftover marker at session start
* fix: report SteamVR start and stop failures from the helper's exit code
* docs: draft 0.4.0 release notes
* docs: add Thor store and launcher media for 0.4.0
* docs: show Steam switching to KDE on Thor
* docs: show Castle Crashers touch layouts and controller choices
* docs: add Amazon game install view
* docs: add trimmed user recording of store downloads
* docs: smoother touch controller recording, GOG sign-in and per-game profile screenshots
* docs: clean desktop round-trip recording replaces the KDE gif and file explorer still
* docs: add multi-controller and Steam Controller media, rebuild desktop gif without glitch frames
* docs: add foldable touch gamepad screenshots from its PR
* docs: add the Discord badge to the 0.4.0 notes and tidy contributor lines
* docs: fold fixes to new 0.4.0 features into their entries, add Follow screen shots, point the changelog at the 0.4.0 tag
* docs: add the Add a game dialog to the non-Steam games entry
* docs: add a TL;DR for Mr. Sujano to the 0.4.0 notes
* feat(profiles): add persistent per-game compatibility profiles
* fix(profiles): show Windows component overrides
Include per-game Windows component selections in the resolved profile summary so the session overlay marks those games as custom and shows the selected components.
* fix(session): detect Proton games across runtime paths
* fix(profiles): select the active Gamescope game
* fix(profiles): improve per-game reset feedback
* fix(profiles): align session components with game overrides
* fix(session): prefer selected Steam game during refresh
* fix(session): resume profile following when reopening games
* chore: keep local dev testing outside the repository
* test(session): remove local dev package path
* fix(session): preserve profiles when refresh fails
* fix(session): reject empty game profile reset scope
* perf(session): cache drawer inventory by refresh revision
* fix(profiles): align game presets and profile reset behavior
* fix(profiles): preserve originals and normalize shortcut ids
* fix(profiles): keep editor scope stable after rebase
* fix(tests): host Compose tests in both build variants
* fix(profiles): recover interrupted component selection saves
---------
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Each game's Windows components now come from the list its own source
trusts, and the ones that list names turn on by themselves. The user's own
on/off switches always win; each automatic row says why it is on.
- Steam games: the Steamworks Shared redistributables Steam installs with
the game (appmanifest SharedDepots, else the client's appinfo.vdf).
Steam keeps its install scripts marked as already run.
- GOG: the build manifest's dependencies. Epic: the manifest's
prerequisite (Unreal's maps to VC++ and DirectX). Amazon: fuel.json
PostInstall. Older GOG/Epic installs get their list fetched once with the
saved sign-in; game files are never downloaded again.
- Custom games (the + button, Add all, migrated folders): one shared Steam
match per game, also used for artwork. An appid from the game's files
turns components on; a name-only match stays Recommended; no match falls
back to the folder scan.
- Steam app info for apps the client never saw comes from an anonymous
Steam PICS lookup (CM websocket, anonymous logon, product info), cached
per appid; the user's Steam sign-in is never used.
- Missing components download in the background on one low-priority
worker that pauses during sessions and waits on battery saver, heat or a
metered network unless the user asked. A game Steam installs during a
session is readied right away so it can be played without ending the
session; the launch waits up to 10 s only for a component still on its
way.
- Page: "On for this game" with reasons, a quiet "Checking what this game
needs..." only for games never worked out, rows that ease in, pieces that
need a download greyed out while offline. The intro names no other app.
- The folder scan skips Unity's *_Data/Managed (Mono, not .NET Framework).
Games folders saved before the settings section went away were still
registered as Steam libraries on Automatic, with no way left to remove
them. Once, at app start and before any scan, each game such a folder
listed becomes an entry of its own, keeping everything keyed by its folder
(chosen exe, shortcut appid, name, Start in, launch options, art,
removal); store installs and steamapps are skipped. The folders stay bound
at their old guest paths, so no shortcut changes, and the saved roots are
cleared. A Games folder stays a library only when Steam installed a game
into it; the others leave the library list, and the runtime forgets them.
* Controller: optional Select button that opens the Steam menu
* Controller: translate the Select-opens-Steam-menu option
* Controller: clearer wording for the Select-opens-Steam-menu option
* docs: evidence for the Select-opens-Steam-menu option
---------
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* feat: Steam's touch controller as on-screen controls (beta)
* fix: Steam touch controls appear once the session makes the device; tidier default layout
* fix: Steam touch layout decoding, saved layouts and new sessions
* docs: Steam's touch controls
* feat: Steam's touch icons, labels and colours on the touch controls; pick and save them like Steam
* feat: Steam touch icon picker as in-session panels; layout colour; docs
* Give each physical controller its own player slot
Every controller fed the one exported pad, so two pads played as one.
The first controller keeps slot 0 (the Deck in a Steam session); further
ones get slots 1-3 as separate Xbox 360 pads, created on first input and
removed on disconnect. In Deck mode only the Steam client sees those
pads and hands them to games through Steam Input. Rumble follows the
slot it names.
* feat: Steam Link's touch menu, per-game input modes, action set editing, add/copy/paste, oval controls, paste control
* feat: Steam touch controls drawn as Steam Link draws them; Steam Link's touch menu and layout tray
* feat: Steam touch controls in DroidDeck's style, D-mark guide button, shake to hide
* refactor: Steam touch controls become an On-screen controls choice instead of a second dropdown
---------
Co-authored-by: maxjivi05 <maxjividen@gmail.com>
Adding and managing your own (non-Steam) games moves out of the Steam
settings into the Games tab, and works like Steam's own non-Steam
Properties.
- A + beside "Games N" opens a compact in-app picker: the storage first,
then that storage's root, every folder, .exe files only. Picking an exe
adds the game with its name, art, Custom badge and Steam shortcut.
- "Add all games in this folder" adds every game folder inside at once.
A summary opens immediately and fills in as each game is found, with a
"?" where the exe was a close call and a red X to remove a game.
- An edit button on each Custom game opens its editor: Name, Target
(ranked exes, Other exe…), Start in, Launch options, the four pieces of
art with thumbnails, and Remove. Edits go through the same Steam
shortcut, so the appid never changes and nothing duplicates.
- Art chooser per piece: images in the game folder, Steam's official art,
SteamGridDB alternatives, your own image, or back to automatic.
- Finding the exe: up to five folders deep, every exe scored (name match,
Unreal -Shipping builds, bin folders and size up; launchers, crash
reporters, installers, redistributables and depth down).
- Real titles from the game's files (Steam manifest, GOG info, the exe's
version info), keeping the folder's spacing when both spell the same
title, underscores read as spaces.
- Art: the exact Steam appid when the game names one, strict name
matches otherwise, Steam's hashed asset paths for newer games,
SteamGridDB as a fallback (built-in key from the SGDB_API_KEY secret,
optional own key in Setup, sealed with the Keystore), and a cover made
from the exe's icon when nothing else has one.
- Removing a game is instant and keeps its files; adding it again brings
it back. Steam's shortcut list is rewritten once, in the background.
- The Games section is gone from Steam settings; folders added before
keep listing their games. Artwork switch and SteamGridDB key are in
Setup.
The stores' sign-ins (files/stores/<store>/credentials.json: access and refresh
tokens, account id and name) were plain JSON. Other apps could not read them, but
every program in the Linux session runs as the app and could. They are now sealed
with AES-256-GCM under a non-exportable AndroidKeyStore key (StrongBox when the
device has one), so the session only ever sees ciphertext.
- Format: a versioned envelope {v, alg, iv, ct}, written atomically and readable
only by the app. No new dependencies (javax.crypto and KeyStore).
- Migration: an existing plaintext file is sealed at the next start, checked by
decrypting it, then the plaintext is removed; users stay signed in.
- No Keystore on the device: the file stays plain and the log says so once per
start.
- A sealed file that can never be opened (tampered, key gone or invalidated,
broken envelope) is removed and that store asks for sign-in again. A transient
Keystore error keeps the file and retries.
Session folders, tool and installer logs and the stores' log now all live under the
app's private files/logs instead of Download/DroidDeck, and every existing "Share
logs" action bundles them into one zip that goes through a final scrub.
- Where: LinuxRuntime.logDir() = files/logs; sessions keep their dated folders and
30-session pruning, tools/ and stores/ beside them. The "Logs" setting keeps its
meaning. Game save backups stay in Download/DroidDeck/Saves.
- Migration: at first start the old session folders, tools/ and loose logs move from
Download/DroidDeck into files/logs (Saves untouched), and every moved folder is
scrubbed under the current rules.
- Scrubbing: one rule set (SecretScrub) for the stores' log and the zip. The scrub
marker carries the rules version, so a rules change re-scrubs every folder at the
next start (in the background, a few at a time). Steam login account names and
emails, account-name fields, OAuth codes, tokens in URLs and private LAN
addresses are removed; Windows exception codes and server addresses are kept.
- Share: one zip of the current session folder plus the last 7 days of stores/ and
tools/, written to cache/share and handed to the share sheet.
A Stores section (rail, under Games; Setup › Stores gate) with each store's sign-in,
library, storefront shelves and a download queue. Each store has two tabs, Store and
Library, and Library filters to All or Installed; libraries open from a saved copy
and refresh in the background, with install sizes on every card. Games install to internal storage,
or a card chosen at Install time, and are registered in the Steam client as non-Steam
games, so they launch through Steam and droiddeck-proton from either the front end or
the client.
- Downloads: GOG, Epic and Amazon engines in Rust (app/src/main/rust/stores, built by
cargo-ndk, nothing compiled in the tree). One adaptive fetch core with a latency
brake, stalled-host handoff and every CDN a store offers. Per-stage progress,
pause/resume, two-step cancel that deletes, failed downloads kept for retry, a
foreground service with Wi-Fi and wake locks and notification controls.
- Games tab: store source chips (Steam, GOG, Epic, Amazon, Custom) and store art.
- Epic: per-launch exchange code from the app and from Steam's Play button,
"Epic sign-in (EOS)", "Launch offline", and a game's web links opened in Android's
browser for EOS consent. The EOS overlay crashed games and is left out.
- Cloud saves (GOG, Epic): pulled before launch, pushed after the game or the session
ends, no upload before a first download, conflicts never overwritten, backups both
ways.
- Logs: every store line redacted; the engine log goes to daily files.
* feat: replace the LXQt desktop with SteamOS-style KDE Plasma
* feat: leaving the KDE desktop logs out through Plasma and returns to gaming mode
* feat: DroidDeck logo wallpaper as the KDE desktop default
* feat: build the KDE wallpaper from the DroidDeck mark artwork
* ci: keep the built desktop package as a short-lived artifact for device testing
* fix: the desktop loading screen no longer promises Steam on the desktop
* docs: the output resize comments name the desktop's KWin
* fix: the desktop package verifies every package's Arch Linux ARM signature and never replaces a published tag
* fix: programs sent to the GPU from the desktop drop its software rendering overrides
* fix: an interrupted desktop install no longer counts as installed
* feat: pin the desktop package to its DroidDeck-Components release instead of the catalog
DirectAudio from its own release: driver set per Proton audio interface (CachyOS fix), the Steam client's own DirectAudio sink, binaries out of tree
Games
- Two driver sets ship from the pinned DirectAudio release (tools/directaudio/release.env =
directaudio-linux-v1.1.0, sha256-checked by tools/directaudio/fetch.sh in CI and
build_local.sh): linux-wine11 for Valve Proton 11 / Experimental / GE-Proton, and
linux-wine11-systhread for Proton-CachyOS, whose Wine carries the system-thread mmdevapi
interface. steam-compatibility picks by whether the Proton's own winepulse.so imports
PsCreateSystemThread, never by the version string (both say wine-11.0; the wrong set is
silence). No matching set: DirectAudio off, Proton's audio runs, logged.
- Proton-CachyOS's launcher pre-sets WINE_AUDIO_DRIVER=pulse,alsa and its mmdevapi reads that
before the registry (Valve's and GE's do not read it): the wrapper exports
WINE_AUDIO_DRIVER=directaudio,pulse as well as writing the registry. On CachyOS this also
makes DirectAudio engage on a game's first launch.
- A wineserver from an earlier Steam verb can save its in-memory registry over the appended
Audio value; the wrapper says so when one is live. Writing through it (wine reg add) and
creating a missing prefix first (proton run wineboot) were tried on the device and withdrawn:
a second Proton/Wine run inside Steam's launch sequence got launches aborted.
- Tests: both sets, no set, no prefix (34 pass).
Steam client audio
- DirectAudio = module-directaudio-native-sink, the game driver's AAudio engine inside the
PulseAudio daemon, one step from Android (adaptive buffer, two-burst floor, primed ring with
fades, reopen on route change, watchdog, limiter). Default. Shared output = the previous relay
route, kept. New pref clientAudioRoute; the old boolean is not read. If the native sink cannot
open its stream the daemon keeps running (.nofail) and ensureClientSink loads the plain AAudio
sink instead, logged to audio.log. Audio bundle stamp bumped.
Out of tree
- app/src/main/assets/directaudio/ is generated and ignored; tools/directaudio-relay/ and the
vendored module-directaudio-sink.c + da_relay_proto.h are gone; tools/aaudio-sink keeps only
module-aaudio-sink (the fallback). The release carries the relay and sink field fixes by
MaxsTechReview (#338), credited there and in its AUTHORS.
Device-proven on an AYANEO Pocket FIT: client sink 12 ms / 4 ms bursts, 0 underruns; FEZ on
cachyos-11.0-20261005-slr on DirectAudio (took pulse before); FEZ on Proton Experimental
unchanged; Curse of the Dead Gods on CachyOS from a cold prefix, DirectAudio on first launch.
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
* Support CJK text with the device's own fonts
The Linux runtime's rootfs ships DejaVu alone, which has no CJK
glyphs, so Chinese, Japanese and Korean text in Steam Big Picture and
on the LXQt desktop draws as tofu boxes (issues #118, #206, #249).
Bind the device's own CJK fonts - Android's world-readable Noto CJK
.ttc, or DroidSansFallback / Source Han - into the guest under
/usr/share/fonts/droiddeck-cjk, so nothing is added to the ~790 MB
runtime image and the coverage follows the device. A new
droiddeck-fonts script, run by droiddeck-session before any program
that queries fontconfig, links the default rules, writes local.conf
with DejaVu first and the CJK families after it, and rebuilds the
fontconfig cache once per set of font files. The desktop's own
fontconfig block moves there, so every mode gets it.
* Fix CJK and Thai: bind the device font directory, not one file at a time
The first cut bound each device font with its own proot -b host:guest. A
per-file binding into a plain directory is not applied here: the guest sees a
zero-byte placeholder where the font should be (stat size=0, fc-scan empty),
so Chinese stayed tofu even though the app had "bound" the font. A directory
binding is what the rest of the runtime relies on, so bind /system/fonts as a
whole under /usr/share/fonts/droiddeck-device. That also brings Thai, Arabic,
Devanagari and the emoji fonts, which the runtime did not have either.
Verified on the AYN Thor: the session's fontconfig probe reports
sans=DejaVu Sans, zh=Noto Sans CJK SC, th=Noto Serif Thai, and Steam Big
Picture in Simplified Chinese renders without tofu (screenshot under
docs/development/evidence/).
---------
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* feat: run a guest agent in every session for commands, focus and the Steam client's DevTools
* feat: give the agent bridge game, input, UI and experiment commands behind a Setup toggle
* feat: droiddeckctl commands for the new bridge, a scenario runner and contract tests
* feat: run cleanup steps after every scenario run so a failure cannot leak into the next
* feat: restart a session that died between scenario runs with start --reuse
* fix: give droiddeckctl stop its own, longer wait for the session's logs
* fix: harden debugging tools access and output