Commit Graph
2151 Commits
Author SHA1 Message Date
Kurt Himebauch bf95a40e3e fix(ci): post new Discord notice for each PR build (#2314)
Post a fresh signed test-build notice for each new PR commit, retire the
previous notice, and include the latest commit subject.
2026-11-08 21:19:22 -05:00
Kurt Himebauch 1355cb3a2b fix(ci): handle empty commit lookup responses 2026-11-08 21:13:53 -05:00
Kurt Himebauch 51407155fc fix(ci): keep commit lookup failures from blocking notices 2026-11-08 21:12:58 -05:00
Kurt Himebauch b4a953c659 fix(ci): post new Discord notice for each PR build 2026-11-08 21:08:22 -05:00
MaxsTechReview 5e438e9248 fix(gog): owned games the listing leaves out stay owned, and search reaches GOG's catalog (#2296)
* fix(gog): owned games the library listing leaves out stay owned

Since the GOG library is read from account/getFilteredProducts, a game
that listing does not return (one hidden in GOG Galaxy, for example)
dropped out of the library, and with it out of the GOG tab, which shows
owned games and the shelves. 0.5.0 read every owned id from
user/data/games and showed them.

The sync now takes the union of the listing and user/data/games. The
listing still names most games at once, and an owned id it lacks is
fetched like any other.

* fix(gog): the GOG tab's search reaches GOG's catalog

GogStoreCatalog.search was never wired to the backend, so searching the
GOG tab only filtered the owned library and the featured shelves; a game
that is neither could not be found. GogBackend now answers search from
GOG's catalog, like the other stores.

* fix(gog): keep cached owned games when the account list is unavailable
2026-11-08 19:37:20 -05:00
MaxsTechReview 6b110581ac fix(gog): install scripts' support files reach the prefix (#2294)
* fix(gog): install scripts' support files reach the prefix

A goggame-<id>.script can copy files into the prefix with supportData
actions: default INI files, Plugins.txt and other settings that mods such
as one-click editions need. Only setRegistry actions were applied, so
those games started without their configuration and ran as the base game.

droiddeck-store-launch now applies supportData after the registry, once
per script revision: copies from {app} and {supportDir} into {userdocs}
and {localappdata}, matching paths without regard to case. Links are
copied as links, paths outside those folders are refused, and existing
files are replaced only when the action asks for it.

* Keep GOG support data copies inside the game and prefix folders

* Copy linked GOG support sources as links and keep a player's own links
2026-11-08 18:45:53 -05:00
MaxsTechReview 92742f37c1 fix(preload): answer netlink requests sent with write and writev (#2304) 2026-11-08 18:40:57 -05:00
MaxsTechReview ecd916d43f fix(input): show the panel tabs under the controls-below-the-game bar (#2302)
* fix(input): show the panel tabs under the controls-below-the-game bar

* fix(input): take the tab row out of the game, not the controls below it
2026-11-08 18:32:40 -05:00
Kurt Himebauch a7c10e3f51 fix(session): give Steam a session bus so launches stop hanging at the install script (#2303) 2026-11-08 16:53:01 -05:00
MaxsTechReview 1760f008ae fix(desktop): Flatpak and Snap apps get the game GPU setting (#2295)
The session's TU_DEBUG=sysmem is meant for the Steam client and
Chromium-based apps. Flatpak and Snap apps inherited it, so emulators
and other programs installed that way rendered through system memory.

droiddeck-game-env now holds the Chromium check next to game_gpu, and a
small droiddeck-game-gpu wrapper applies both to any program. The
AppImage, Flatpak and Snap launchers use it, so the rule lives in one
place.
2026-11-08 14:39:31 -05:00
MaxsTechReview 3bb279f635 fix(appimage): emulators and other AppImage programs get the game GPU setting (#2288)
The session sets TU_DEBUG=sysmem for the Steam client's interface and hands
games their own value in DROIDDECK_GAME_TU_DEBUG, which droiddeck-game-env
applies to Steam launches (#1188). droiddeck-appimage-run never did, so
emulators and other AppImage programs rendered every pass through system
memory instead of Turnip's per render pass choice.

Apply the game value in droiddeck-appimage-run the same way: an empty
value unsets TU_DEBUG, any other value replaces it. Chromium-based apps,
like the Steam client's own interface, keep the session's setting.
2026-11-08 12:23:30 -05:00
MaxsTechReview 3fef1f3fa1 fix(proton): a Proton picked for a game in Steam is kept (#2284)
fix(proton): a Valve Proton picked for a game in Steam stays on the ARM64 build made from it

Steam lists Valve's own Proton Experimental and Proton 11.0 next to the
DroidDeck tools. They are not runnable here, so a per-game pick of one was
replaced with the default. That used to be Proton Experimental ARM64, so the
pick looked kept; since an installed DroidDeck-Proton became the default, the
game is moved to DroidDeck-Proton instead.

When Steam records one of those tools for a title the sync already knows
(a title it mapped or one with a recorded pick), the title now gets the
DroidDeck tool built from the same Valve depot, stops following the default
and the choice is mirrored into the app's per-game setting. The same applies
to Steam's default. Titles nobody picked anything for still follow the
default, and Valve tools with no ARM64 build still fall back to it.
2026-11-08 12:03:21 -05:00
MaxsTechReview a4f26799ab fix(mesa): Zink on PowerVR shows colour again instead of grayscale (#2287)
Mesa 26.0.8, which the Ubuntu runtime builds, carries the backport of
"zink: create views for samplers lazily", which dropped the depth/stencil
aspect check in init_sampler_view(). On drivers with
needs_zs_shader_swizzle (Imagination) every colour view with a constant-1
alpha, such as RGBX/BGRX textures, then got the red-only depth swizzle
view, so Steam's interface and games showed red as R=G=B.

Carry Icenowy Zheng's upstream fix d55418dae7 (Mesa MR 41923), which
restores the aspect check. It applies on top of patch 0004.
2026-11-08 11:48:11 -05:00
MaxsTechReview 08a6a3cba8 ci: run approved fork PR compile jobs on the disposable fork runner (#2246)
* ci: run approved fork PR compile jobs on the disposable fork runner

* ci: ignore fork runner heartbeats from the future

* ci: target the fork runner by its own label

* Read the fork runner heartbeat from a public gist

* Fall back to an anonymous read of the fork runner heartbeat
2026-11-08 11:40:12 -05:00
MaxsTechReview 005fec2125 chore: pin gamescope to the DroidDeck-Components p23 release (#2285) 2026-11-08 11:37:54 -05:00
MaxsTechReview 2e70b8ed73 fix(gamescope): taps reach dialogs and windows away from the screen origin (#2280) 2026-11-08 10:44:00 -05:00
MaxsTechReview 74c0f2127a fix(proot): lay out ARM64 programs like the kernel so large reservations fit (#2279) 2026-11-08 10:43:57 -05:00
Kurt Himebauch 2bd7df5e1a chore: bump version to 0.7.0 (18) (#2278) 0.7.0 2026-11-08 09:36:10 -05:00
Kurt Himebauchandmaxjivi05 b7b96875a1 docs: DroidDeck 0.7.0 release notes (#2170)
* docs: DroidDeck 0.7.0 release notes

* docs: add 0.7.0 release note media

* docs: drop the 30 second summary from the 0.7.0 notes

* docs: add the dual-screen Dashboard shots to the 0.7.0 notes

* docs: show the Dashboard as one stacked dual-screen image

* docs: add the swap screens GIF to the 0.7.0 notes

* docs: swap in the new Syncthing screenshot

* docs: add the HUD dock GIF to the 0.7.0 notes

* docs: add the Game Jolt screenshot to the 0.7.0 notes

* docs: show the full screen in the HUD dock GIF

* docs: merge the GPU bullets, add the no proprietary components line, put images above their bullets

* docs: add the 0.7.0 APK download button to the release notes

* docs: add the first-time contributors to the 0.7.0 notes

* docs: add KeegantheVeganat0r as a first-time contributor

* docs: add the shared Steam libraries screenshot to the 0.7.0 notes

* docs: rewrite the shared Steam libraries bullet and move it up

* docs: add the Mali support photo to the 0.7.0 notes

* docs: center 0.7.0 release media

* docs: credit The412Banner for Mali support in 0.7.0 notes

* docs: add the KDE desktop GIF to the 0.7.0 notes

* docs: add the desktop and swapped game clips to the 0.7.0 notes

* docs: use the Duo photo for the swapped screens

* docs: replace the swap screens GIF with the Duo recording

* docs: drop the swap screens GIF

* docs: keep a blank line before each release image

* docs: tweak 0.7.0 release notes

* docs: move smaller 0.7.0 items to improvements

* docs: fold the bottom-screen HUD into the Strip HUD bullet

* docs: pair the swap screens and KDE desktop media

* docs: move Game Jolt and Syncthing up in 0.7.0 features

* docs: put the swap screens and KDE desktop cluster after Mali in 0.7.0 features

* docs: reword shared Steam libraries and reorder KDE desktop bullet

* docs: add recent merged PRs to the 0.7.0 notes

* docs: auto component updates follow DroidDeck-Proton only

* docs: add input profiles, low-RAM memory, driver Auto and other recent changes to the 0.7.0 notes

* docs: add the second-screen layout editor to the 0.7.0 controller profiles notes

* docs: refresh the 0.7.0 pull request and contributor counts, mention controller profiles in the summary

* docs: 0.7.0 notes add the latest fixes and the DroidDeck-Proton, DD-Turnip and component changes

Adds the user-visible pull requests merged after the last refresh (Library
sort, runtime pack update, desktop app launches, GitHub AppImage variant,
DroidDeck-Proton default, component auto-update cleanup, UBWC and FEX preset
settings, controller navigation) and a section for what shipped in
DroidDeck-Proton 11-11.10 to 11-12.3, DD-Turnip 0.4.0 and DroidDeck-Components
since 0.6.9.

---------

Co-authored-by: maxjivi05 <maxjividen@gmail.com>
2026-11-08 09:32:48 -05:00
MaxsTechReview 51e5e3a2a4 ci: a finished build reports on pull requests from forks (#2277)
When a Build APK run finishes, Build validation finds its pull request with
commits/{sha}/pulls, which GitHub answers with an empty list for a commit that
only exists on a fork. The validator then took the build as superseded, so the
"Build APK" status of every fork pull request stayed at "awaiting APK
compilation" after a successful build. It now falls back to the open pull
request for the run's head owner and branch, still requiring the head commit
to match.
2026-11-08 09:07:36 -05:00
MaxsTechReview c755d05473 ci: cache the pinned Turnip archive and retry its download (#2276)
* ci: cache the pinned Turnip archive and retry its download

"Prepare graphics driver variants" fetched the same checksum-pinned Banners-Turnip
zip from GitHub on every run with a single 120 s attempt, so a 502 or a read
timeout failed whole PR builds three times today. The archive is now cached
between runs (it is still checked against its SHA-256 after a restore), and a
cold download is retried on timeouts, 429 and 5xx with a growing pause.

* ci: keep PowerVR's verified downloads between runs

tools/powervr/fetch.py already keeps checksum-verified downloads in
~/.cache/droiddeck-build, but CI never saved that folder, so every run fetched
the PowerVR components again and a read timeout failed "Build the add-on
packs". The folder joins the existing pack-inputs cache, keyed on
release.json too.
2026-11-08 09:07:31 -05:00
MaxsTechReview aa883830ca fix(session): give the runtime a machine ID so D-Bus programs such as melonDS start (#2275)
* fix(session): give the runtime a machine ID so D-Bus programs start

The Ubuntu runtime ships an empty /etc/machine-id for systemd to fill on first
boot, and nothing fills it in a DroidDeck session. libdbus aborts when it needs
the ID ("D-Bus library appears to be incorrectly set up"), so melonDS closed at
once from the desktop and GTK Flatpaks started outside the session bus failed.

The session now writes a fresh ID once when the file is empty or malformed and
never changes a valid one.

* fix(session): check the whole machine ID file and reject the all-zero ID
2026-11-08 08:54:56 -05:00
MaxsTechReview 45e39b7aaf fix(desktop): catalog AppImages such as RPCS3 start from the desktop menu again (#2274)
fix(desktop): catalog AppImages start from the desktop menu through the shipped runtime

RPCS3 from the desktop menu exited at once: its own AppImage runtime runs
dwarfsextract from a memfd, which PRoot cannot execute (EACCES), and it has no
fallback. Emulator rail launches already avoid this by starting arm64 images
through the shipped uruntime (#1191); the menu entries the catalog writes did not.

The rule now lives in one launcher, droiddeck-appimage-exec, used by the session
and by the catalog's menu entries. Entries written by older versions are moved
to it with the existing menu migration.
2026-11-08 08:39:23 -05:00
MaxsTechReview bc99cacd02 fix(desktop): a GitHub link to one AppImage installs and updates that variant (#2273)
* fix(desktop): a GitHub link to one AppImage installs and updates that variant

* fix(desktop): latest-release links, bad escapes and 32/64-bit variants

A /releases/latest/download/<file>.AppImage link now names its asset too, a
malformed %-escape in the field no longer throws while the dialog composes,
and x86-32 and x86_64 assets no longer collapse to the same variant once
version numbers are dropped.
2026-11-08 08:07:28 -05:00
MaxsTechReview 2beeb715fd fix(runtime): an update that brings a new PRoot pack no longer asks to install the runtime again (#2270)
* fix(runtime): an update that brings a new PRoot pack no longer asks to install the runtime again

* A pack-only install recovers an interrupted swap first and falls back to the full install
2026-11-08 06:27:33 -05:00
MaxsTechReview 39469e6e8f fix(proton): an installed DroidDeck-Proton replaces a Proton Experimental default nobody picked, and added shortcuts follow it (#2266)
* fix(proton): an installed DroidDeck-Proton replaces a Proton Experimental default nobody picked, and added shortcuts follow the default

* test: an owned shortcut left on the previous default follows a default change
2026-11-08 06:07:53 -05:00
MaxsTechReview 15baa296bb fix(storage): a Second library folder that is there is used even when its volume state isn't mounted (#2258)
fix(storage): a saved game folder that is there stays the library
2026-11-08 00:32:04 -05:00
MaxsTechReview e4a4775be5 fix(input): taps outside the PC keyboard reach the game while it is open (#2257)
* fix(input): taps outside the PC keyboard reach the game while it is open

* fix(input): the game's cursor stays visible while only the PC keyboard is open

* fix(input): a touch cancelled mid-stream stays closed until the finger lifts

* A resize also ends a pending two-finger touch

* A new touch clears a dismissal left by a stream that ended elsewhere

* A new touch is not held back by a three-finger tap whose end was consumed
2026-11-07 23:24:53 -05:00
MaxsTechReview 77ef10d601 fix(library): added and Battle.net games sort by when they were played and installed (#2256)
* fix(library): added and Battle.net games sort by when they were played and installed

Recently played and Recently installed put every added game, Battle.net
games included, at the bottom: nothing recorded a launch or an install time
for them, and the Steam play-time lookup was never reached once an entry had
a game. Launching an added game now records its play time, added games carry
their folder's install time (kept in the library cache), Battle.net installs
report theirs, and a zero time falls through to the next source.

* fix(library): an added game's play time is recorded only after it launches and kept when it is rebuilt

* fix(library): an added game's play time is recorded only when its launch is accepted

* fix(library): an added game's play time is recorded when its session actually starts

* fix(library): an added game's play time is recorded when its session service starts
2026-11-07 23:17:43 -05:00
MaxsTechReview 914b3588e1 fix(drivers): leaving a driver bundle no longer keeps its runtime half, and the Auto display picks the latest pair (#2255)
* fix(drivers): leaving a driver bundle's display half also drops its runtime half

Picking either half of an Android + Linux bundle selects both, but picking
another display driver afterwards changed only the display. The session
kept loading the bundle's Linux driver, so switching back to DroidDeck's
drivers could still leave the session failing to start. The runtime driver
now goes back to the default when the display leaves the active bundle; a
runtime driver chosen on its own is kept.

* fix(drivers): picking the Auto display hands both halves to Auto's latest DD-Turnip pair

* fix(drivers): the Auto display pick puts the display on Auto even when no pair fits the GPU
2026-11-07 21:47:04 -05:00
MaxsTechReview 2ade269be3 fix(gamescope): direct-touch drags work again in games that confine a hidden cursor (#2220)
* gamescope: a confine is relative only while it holds the X pointer

Patch 0128 made every hidden-cursor confine relative. Games that hide the
system cursor, draw their own and confine the pointer to their window then
took the host lock, and a direct touch drag became camera motion with no
button held, so cards and items could not be dragged.

A confine now goes relative once the X pointer stays away from the seat
position while input moves, as when a game recentres it or clips it to a
small rectangle, and returns to absolute when the pointer follows again or
the confine ends. Locks and the warp follow rule are unchanged.

* gamescope: a constraint without a hint is relative only while the game holds the X pointer

Xwayland turns a hidden-cursor grab into a lock with no cursor position hint, so the confine-only rule never applied to games that draw their own cursor (Stardew Valley, Balatro). A hinted constraint is relative at once, as upstream. An unhinted lock or confine goes relative once the X pointer stops following the seat's motion, which a recentring or clipping game does and a drawn-cursor game does not.

* gamescope: a pointer constraint is relative only while the game holds the X pointer

Stardew Valley's grab with a hidden cursor becomes an Xwayland lock with a cursor position hint, which upstream made relative at once. Without relative mode that lock still follows gamescope's relative motion and touches still place the pointer, so the hold rule now decides for every constraint, hinted or not.

* gamescope: a hinted lock starts relative and is released once the X pointer follows

Releasing a hinted lock only through the hold rule let a recentring game's first touch swipe press the button. A hinted lock now starts relative as upstream and is released after 30 moving frames on which the X pointer follows the motion gamescope sends, counted from the relative motion while the seat is locked.

* gamescope: count away frames within one half-second window

* gamescope: a hint that arrives with the game's first warp starts the lock relative

* fix(input): end the touch press when a program locks the pointer mid-swipe

A game that only shows its pointer lock after its first warp took the first
swipe as an absolute drag, with the button held until the finger lifted.
The first locked move now ends the forwarded touch before sending deltas.

* gamescope: a new focus window or constraint starts its own pointer hold

A held state from one constrained window carried over to the next one
when focus moved before a reset frame. Track the input focus window and
the constraint, and restart the hold when either changes.

* gamescope: read the pointer constraint under the wlserver lock

GetCursorConstraint asserts the lock is held, so the hold tracker
aborted as soon as a program constrained the pointer.

* fix(input): a mid-swipe pointer lock ends the touch but keeps a held button

The first locked move cancelled the whole direct-touch hold, releasing a
right button held by a long press. It now cancels only the forwarded touch;
the held button is released when the finger lifts, as before.

* fix(input): extra fingers during a locked swipe stay out of the cancelled touch

Once a locked swipe has ended the forwarded touch, a second finger restarted
it with a new touch-down while the swipe carried on as relative motion. Extra
fingers are now ignored until the swipe ends; the final lift still releases a
held button.

* fix(input): a swipe that ended its touch stays closed until the finger lifts
2026-11-07 21:30:21 -05:00
MaxsTechReview 0d034b1996 fix(input): restore the rest of what #1439 removed, and keep the editor on the bottom screen (#2242)
* fix(session): close the bottom panel from the docked menu's Close again

* fix(input): keep imported screen keys on screen when the gamepad is hidden

Screen keys used to be shown on their own, whatever the gamepad did. Since
they were merged into the gamepad layout they disappeared with a controller
connected, in desktop sessions, with on-screen controls set to Never, in
Steam + QAM mode and in Steam's touch mode.

Elements now carry an always-shown flag. The screen key migration sets it on
imported keys (and once on keys merged by earlier builds), and the on-screen
controls keep flagged elements drawn while the rest of the pad is hidden,
in buttons-only mode and with the quick toggle, without duplicating them in
the unfolded strip.

* fix(dual-screen): give the profile controls panel the bottom bar with swap

* fix(dual-screen): keep the layout editor on the bottom screen

The bottom panel was recreated above an open input editor or input
settings window whenever it closed and reopened (session stop/start, or
the bottom screen briefly reported as taken), hiding the editor. The panel
now waits while one of our input windows holds its display and reopens
when the last one closes.

An app arrival recorded before one of our windows covered the bottom
screen no longer marks the screen taken, the editor picks its display only
when a display is added or removed, and it skips a bottom screen another
app holds.

* fix(input): label keyed D-pads and sticks with their keys

Screen key D-pads and sticks used to show each direction's key (W, A, S, D)
when labels were on. The unified renderer drew no direction labels and only
offered Show label for buttons and gamepad sticks, so imported labels did
nothing.

D-pads and sticks bound to directional keys now draw each bound key's name
at its direction through the shared key-label helper, and Show label is
offered for every D-pad and stick.

* fix(input): remember the layout editor's snap choice

* refactor(input): drop controller pref setters and drawer field nothing uses

* fix(input): restore the Deck tabs and right trackpad in the unfolded strip

With Deck controls, the unfolded strip used to offer the Gamepad, Grips,
Left, Right and Both tabs and put a trackpad in the right stick slot. The
unified strip only showed the gamepad with two sticks.

For Deck pads the strip bar now carries the shared Deck panel tabs and
title, the other tabs show the same stock Deck panel layouts as the second
screen, and the docked gamepad takes its stick or trackpad per side from the
Deck gamepad layout. Other pads keep the plain two-stick strip.

* fix(input): carry the Deck gamepad stick or trackpad choice into its layout

The Deck controls Gamepad tab used to let each side switch between a stick
and a trackpad. That choice is now part of the editable Deck gamepad
layout, but the saved choice was never moved over and its setter was left
without callers.

The library upgrade now applies a saved non-default choice to the Deck
gamepad layout once, only while that layout is still the stock one, and the
unused setter is removed.

* chore(i18n): drop the Deck surface switch string nothing shows

* fix(input): offer Show label only where a label can be drawn

* fix(input): Show label follows the unsaved action and diagonal-only sticks

The element properties now get the editor's draft action, so changing a
stick or D-pad to keys offers Show label before saving. A stick bound only
on its diagonals counts as labelled too.

* fix(input): only sticks count their diagonal keys for Show label

Diagonal key names are drawn on sticks only, so a D-pad bound just on its
diagonals no longer offers a label it can't show.
2026-11-07 21:04:34 -05:00
Kurt Himebauch ef46c011db fix: keep the bottom-screen menu and layout editor open when the screen turns off (#2247) 2026-11-07 20:11:20 -05:00
MaxsTechReview 5b2f7a9a6d fix(storage): a Second library on a raw /mnt/media_rw path is used again (#2245)
fix(storage): check a raw /mnt/media_rw library against its storage volume

A Second library picked as /mnt/media_rw/<volume>/... was always treated as
unplugged, because Android only reports a volume's state for its /storage
path. Sessions then ran with internal storage only and the library's games
were missing. Map the path to its /storage form before the lookup, reusing
UsbLink.storagePath, and drop the copy in SteamLibraries.
2026-11-07 19:32:13 -05:00
Kurt Himebauch 10cfc6c6b2 feat: let users turn off the low-storage warning (#2244) 2026-11-07 19:09:51 -05:00
MaxsTechReview 4948f73912 test: skip the unscrubbable session log test when file permissions are not enforced (#2241) 2026-11-07 18:37:44 -05:00
Kurt Himebauch d29a1a2dc2 ci: build and test on root self-hosted runners (#2237) 2026-11-07 17:02:19 -05:00
MaxsTechReview 8fa30b99f9 fix(input): restore the controls, panels and settings #1439 removed (#2238)
* fix(input): restore on-screen touch behaviour: slide between buttons, mouse pass-through, keyboard on release, overlay haptics, stick reach and hit areas

* fix(dual-screen): restore second-screen bars, swapped Terminal and Deck panel tabs

* fix(input): fit on-screen layouts to the real view size, cutout, Steam + QAM mode and unfolded strip

* fix(input): unfolded strip keeps press haptics

* fix(input): restore layout import/export, element editor rows and layout tools

Bring back .icp layout import and export on the saved layouts page, the
per-element image, opacity and label controls, a uniform size slider and
reset positions in the layout editor, and non-destructive Steam, QAM and
keyboard button toggles stored on the layout style. Remove strings left
unused by the input profile unification.

* fix(input): keep hit slack to gamepad-shaped buttons and fit touch tests to saved layout geometry

* fix(input): button size regenerates the gamepad and scales spacing

A generated gamepad now stores its button size and is regenerated at that
size, so spacing follows the radius and the layout keeps regenerating on
rotation. Edited layouts scale positions from their anchor edge or centre
so gaps grow and shrink with the controls.

* fix(input): button size rescales moved gamepads around the generator

Gamepad layouts that no longer match the generated positions exactly were
scaled element by element from screen thirds, which split the face buttons
and D-pad across anchors. Gamepad controls now take the generator's
positions at the new size plus each control's own offset from the
generated position, so groups keep their shape and spacing.
2026-11-07 16:36:23 -05:00
MaxsTechReview a33954b8bd perf: answer Steam's missing-file checks on SD and USB libraries from the directory cache (#2212)
* perf: answer Steam's missing-file checks on FUSE libraries from the directory cache

Before creating and committing each file, the Steam client checks whether it
already exists under its exact, lower-cased and folded spellings. On an SD or
USB library reached through Android's FUSE layer every one of those misses is a
round trip to MediaProvider (Brawlhalla: about 65,000 misses, 92 of the 161 s
of preallocation and 60 of the 93 s of commit).

The client already caches the listings of its steamapps directories on FUSE and
keeps them exact through its own changes, inotify and a short TTL. access() now
answers a name that is absent from a live listing of its directory without
asking the filesystem. Directory paths match case-insensitively only when the
library's filesystem folds case, and names compare case-insensitively, so an
existing file is never reported missing.

* fix: reuse a listing for a differently cased folder only when the whole path folds case

Checking that steamapps alone folds case let a listing of one folder answer
for a different folder below it whose name differs only in case. The fill
now compares the listed folder with its fully case-swapped path below
steamapps, so a listing is reused across case only when the filesystem
folds every level.

* fix(dircache): match a folded listing only below the same prefix and skip it during a tracked change

* fix(linuxfs): a folder renamed or removed above a cached listing drops that listing

* fix(linuxfs): watch the folders above a cached listing so a rename or removal by any process drops it

* fix(linuxfs): also watch the folders above steamapps, and stop a stuck probe from hanging the tests

* fix(linuxfs): a listing under a symlink or an unwatchable folder no longer answers absent lookups

* fix(linuxfs): a symlink check that cannot be watched also stops absent answers

* fix(linuxfs): a differently cased lookup reuses a listing only for the same folder
2026-11-07 16:36:15 -05:00
Kurt Himebauch 3526309f88 feat(session): setting to choose the Android keyboard for game text fields (#2236) 2026-11-07 16:19:40 -05:00
MaxsTechReview be0fe35271 fix(proot): let the fast path fall back when Android 10 refuses statx (#2224) 2026-11-07 15:48:44 -05:00
MaxsTechReview 7f0427b830 fix(input): L2/R2 keys stop overriding analog trigger axes (#2205)
fix(input): stop L2/R2 keys from overriding analog trigger axes

Pads such as the GameSir X2 Pro send KEYCODE_BUTTON_L2/R2 alongside
their analog trigger axes. Each key-down and every key repeat set the
trigger to full, and the next motion event set it back to the axis
value, so a held trigger jumped to full. Android repeats only the most
recently pressed key, so with both triggers held one side kept being
forced to full while the other tracked its axis.

When a device reports an analog axis for a trigger side (LTRIGGER or
BRAKE, RTRIGGER or GAS, or the wired Xbox Z/RZ layout), its key no
longer drives that trigger. Key repeats never change a trigger value.
Pads with digital-only triggers keep the key behaviour unchanged.
2026-11-07 15:48:41 -05:00
MaxsTechReview 2476c824f6 fix(dual-screen): docked handhelds switch to single-screen mode (#2232)
* fix(dual-screen): docked handhelds switch to single-screen mode

With Dual screen on Auto, a dual-screen handheld connected to a wired
external display (dock, HDMI or USB-C monitor) no longer puts the menu,
tabs or session controls on the built-in bottom screen, which nobody can
see while it sits in a dock. The launcher and sessions use the single-screen
layout on the main screen, which the external display mirrors. A bottom
panel opened automatically closes once when the dock is connected and comes
back after undocking.

XR glasses, virtual and overlay displays and switched-off displays do not
count as a dock, and Dual screen set to On keeps the bottom screen.

* fix(dual-screen): only an automatic bottom panel closes on docking, and glasses are told apart from the dock display

* fix(dual-screen): keep the automatic-panel state across activity recreation and reconcile docking before settling the panel
2026-11-07 15:48:17 -05:00
MaxsTechReview d74575ed7f fix(components): DXVK Auto on Adreno 6xx keeps DroidDeck-Proton on DXVK-gplasync 2.7.1 (#2226)
* fix(components): DXVK Auto on Adreno 6xx keeps DroidDeck-Proton on DXVK-gplasync 2.7.1

* fix(components): DXVK Auto says so when the pinned DXVK could not be installed

* fix(components): a DXVK the player picked is shown as their choice, not a failed pinned install
2026-11-07 15:48:14 -05:00
MaxsTechReview e4d4096342 fix(drivers): a driver repo that fails to answer no longer changes the Auto pick (#2233)
* fix(drivers): a driver repo that fails to answer no longer changes the Auto pick

The release check reads every driver repo and saved the list even when one
of them failed, so that repo's drivers vanished until the next good check.
When GitHub rate-limited or dropped the DroidDeck driver repo, Auto on an
Adreno 6xx saw no DD-Turnip release, switched to Banner's Turnip, and then
switched back after the next clean check.

A repo that fails now keeps its releases from the last good check, while
still being recorded as failed. A repo that answers and no longer lists a
driver still drops it.

* test(drivers): carry-over is checked through refresh with one repo failing

* fix(drivers): drop a repo's partial results when its answer fails and keep the refresh test offline
2026-11-07 15:48:09 -05:00
KeegantheVeganat0r 11218f0b24 perf(hud): reduce Strip rendering cost with bitmap graph and logo (#2235)
perf(hud): rasterize Strip graph and logo separately

Replace PR2194's whole-View software layer with a hardware-accelerated
Strip that rasterizes its graph and logo into small reusable bitmaps.
Keep the 66 ms graph invalidation cap, clear stale graph pixels, and
refresh cached logo colours when the theme changes.

Include the comparison method and six sanitized benchmark samples.
With matched Steam navigation, the hybrid averaged 12.2% less UI-thread
CPU and 34.0% lower draw p95 than the PR2194 software path. App-process
CPU averaged 5.9% lower in this run; whole-device and battery savings
are not established. Current-build physical flicker confirmation is
recorded separately from timing validation.

Validation: all 12 DroidDeckHudPanelTest checks passed; comparison APK
built and six alternating device samples completed with matched input
counts, no focus loss, thermal status 0, and no frame metric report drops.
2026-11-07 15:41:46 -05:00
Kurt Himebauch d9bf6d8a17 feat: move UBWC compatibility from Components to Settings (#2008)
* feat: move UBWC compatibility from Components to Settings

* fix: update driver menu tests for the moved UBWC restart check

* fix: load saved UBWC mode at startup and block Settings restart during runtime operations
2026-11-07 15:39:55 -05:00
MaxsTechReview 041c3b1b55 ci: run compile jobs on the org workstation runner when it is idle (#2234)
* ci: run compile jobs on the org workstation runner when it is idle

* ci: pick the compile runner right before each heavy job

* ci: cover the runner picks in the job dependency test
2026-11-07 15:00:39 -05:00
Kurt Himebauch e5434117f2 fix(input): controller navigation works across the Controller tab and profile menus (#2231)
* fix(input): controller navigation works across the Controller tab and profile menus

* fix(input): dialog choice rows expose their checked state
2026-11-07 14:37:00 -05:00
MaxsTechReview b474cba79e fix(dual-screen): bring back the trackpad and Deck panels on the second screen (#2229)
Keyboard + trackpad and Deck grips + trackpads are second-screen panels again, rendering the stock layouts without changing the input profile. The last panel is remembered separately for desktop and game sessions; desktop sessions start on the trackpad. A Deck panel without the Deck pad falls back to the default. Stock panels left Steam blue return to the neutral look once.
2026-11-07 14:36:30 -05:00