Commit Graph
1061 Commits
Author SHA1 Message Date
The412Banner ef4e43032c GFN games: five smaller cards per row 2026-10-26 18:25:14 +00:00
The412Banner 62f49756bf GFN games: up to 1000 shown, search covers the whole catalog, full library marks
The first test showed 240 games: catalog.public.list stops at its default limit.
Load 1000, show NVIDIA's total, search through the core's searchQuery so every game
can be found, and page through the account's library for the in-library marks.
2026-10-26 18:25:14 +00:00
The412Banner 510c7e35e6 GFN build: vendored mtu with a versioned Android target for bindgen
cargo-ndk sets bindgen's per-target clang arguments itself, so the environment
workaround never reached the mtu build script. mtu 0.3.0 is vendored with one
build.rs change and patched in for the GFN crate and the OpenNOW workspace.
2026-10-26 18:25:14 +00:00
The412Banner 53b5fde2ff GeForce NOW store: sign-in, game list and native player
- GfnCore: OpenNOW's core service as a child process (newline-delimited JSON); turns
  OpenNOW's analytics and crash reports off.
- GfnStreamer: the JNI streamer engine with a polling thread for answers and events.
- GfnActivity: NVIDIA device sign-in (code + link), NVIDIA's full game list with search,
  games in the account's library marked.
- GfnPlayerActivity: catalog.launch.inspect -> session.create -> queue polling ->
  streamer.prepare -> start, onto a SurfaceView; controllers mapped to XInput like
  OpenNOW; leaving asks first and ends the session.
- Stores page: a GeForce NOW chip opens it. Both screens run in their own :gfn process.
Not compiled locally (no Android SDK here); CI is the first compile.
2026-10-26 18:25:14 +00:00
The412Banner d9efc1efee GeForce NOW: streamer host library (libdroiddeckgfn.so)
Runs OpenNOW's native streamer engine on its own thread with the Android media
backend. JNI for com.droiddeck.launcher.stores.gfn.GfnStreamer: open/close, JSON
commands in, one poll queue for responses and events out, the player Surface, and
gamepad (XInput layout) and key input into the engine's input queue.
Builds for aarch64-linux-android and links only Android system libraries.
2026-10-26 18:25:14 +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 8df90c30dd fix(fex): read the fallback FEX version from droiddeck-fex-update
The pin moved there from droiddeck-steam-x64, so the client settings sheet
and its test read it from the new script. The x86-64 client notes now name
the updater and Components' FEX watcher.
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
Kurt Himebauch 749ade4a45 fix(input): delay held QAM to 700 ms 2026-10-26 13:20:51 -04:00
Kurt Himebauch fa5506df35 fix(steam): preserve Back taps and recover QAM controls 2026-10-26 13:13:08 -04:00
Kurt Himebauch dde1a55d00 feat(input): pass held Back through as Steam QAM 2026-10-26 12:49:51 -04:00
Kurt Himebauch 6a5dfe1486 feat(steam): sync QAM brightness and volume with Android 2026-10-26 12:32:36 -04:00
maxjivi05 9b68b33e73 fix: pick the HUD surface by the scene's draw order 2026-10-26 12:02:17 -04:00
maxjivi05 1f60e57749 fix: time the HUD graph from the game's frames as shown on screen 2026-10-26 12:02:17 -04:00
Kurt Himebauch eaaecf0661 feat(session): add portrait sessions and controls below the game (#1612) 2026-10-26 12:01:44 -04:00
0x1Nawaf d65912f0c5 fix: stop starting a session on the slow proot (#1395) 2026-10-26 11:41:18 -04:00
Kurt Himebauch 5d945d7784 refactor: remove duplicate session frame limiter (#1616) 2026-10-26 11:25:31 -04:00
maxjivi05 ee1b3b26e1 fix: clip damage against the buffer committed with it 2026-10-26 10:50:19 -04:00
maxjivi05 9c02233b06 fix: clip damage to the surface and let the toplevel's size count for coverage 2026-10-26 10:50:19 -04:00
maxjivi05 f98c272300 fix: compare the window's shown size with the scene 2026-10-26 10:50:19 -04:00
maxjivi05 744a42d324 fix: count one shm window, only after new GPU frames stop, with damage in buffer pixels 2026-10-26 10:50:19 -04:00
maxjivi05 30da4d2bcd fix: count a desktop window game's frames for the performance HUD 2026-10-26 10:50:19 -04:00
maxjivi05 e492a78f55 fix: treat a product.db with a damaged install record as unreadable 2026-10-26 10:30:16 -04:00
maxjivi05 538b5c5270 fix: hide registry-only games when product.db lists none, keep the Agent off without the game storage card 2026-10-26 10:30:16 -04:00
maxjivi05 be5bec2d44 fix: keep every game library mounted for Battle.net's Agent and drop games it no longer tracks 2026-10-26 10:30:16 -04:00
maxjivi05 fd9de4a21e fix: list Battle.net's games in a grid that scrolls down 2026-10-26 10:10:31 -04:00
The412Banner 1b3814a587 Hold games to the frame limit in Performance mode (#1609)
A frame limit only paced what reached the screen: a game without vsync
kept drawing hundreds of frames a second that were thrown away (AIO at
a 60 fps limit drew 155 to 2,446 fps), so the limit saved no power.

With Performance mode on and a frame limit set, the session now sets
gamescope's per-game limit over gamescope_control (gamescopectl
debug_set_fps_limit). gamescope's limiter then has its WSI layer hold
Vulkan games, DXVK and VKD3D included, to the limit. gamescope's own
--framerate-limit option is reset on its first frame in 3.16.29, and
Steam resets the per-game limit while it starts, so the session watches
gamescope's limiter state file and sets the limit again whenever it is
off (a once-a-second check with shell builtins, no process started).
With Performance mode off, a limit paces the screen only, as before.

The session also gives gamescope a fixed limiter state file path, so
gamescope stops leaving a new one behind on every start, and removes
the old ones.

Device-proven on the AYANEO Pocket FIT (Turnip, AIO D3D11, 45 s runs on
battery, three runs each): at a 60 fps limit the game held exactly
60.0 fps and the device drew 7.08 W instead of 9.45 W, with 1.3 instead
of 2.6 busy cores and 5 instead of 11 % GPU load. No limit: unchanged.
2026-10-26 09:16:05 -04:00
Kurt Himebauch 78f95c5a0c feat(ui): support portrait launcher layouts (#1606) 2026-10-26 09:14:35 -04:00
maxjivi05 db56cff880 fix: check a Battle.net game for updates again when the last check failed 2026-10-26 09:01:02 -04:00
maxjivi05 c48297e0d1 fix: wait for a cancelled Battle.net job before removing it, and bound uninstall waits
A cancelled install now waits for its Agent job to end before the
uninstall runs, and removes the folder only once the Agent no longer
lists the game or the folder is empty. Uninstall gives up when Battle.net
or a game keeps the prefix busy for a minute, so the page falls back to
opening Battle.net. An uninstall only counts when the Agent reports the
game as not installed.
2026-10-26 09:01:02 -04:00
maxjivi05 b887e8653d feat: install Battle.net games from Stores with downloads, updates and uninstall
Battle.net games now install like Epic, Xbox and itch games: Install,
pick a location, and the download runs in the Downloads tab while the
Stores page stays open. droiddeck-battlenet starts Blizzard's own Agent
on its own under a headless gamescope and drives its local API, so no
window opens and nothing waits on the Battle.net client.

- Progress, speed and time left come from the Agent, with pause, resume
  (the Agent keeps what it downloaded) and cancel, which uninstalls the
  partial game and removes its folder.
- A job only finishes once the Agent has really run it and the game is
  playable; the first status after a request can still describe the
  previous operation.
- Installed games check Blizzard's version service and show Update when
  the build on disk is behind; the update repairs missing files too.
- Battle.net games can be uninstalled from their page through the Agent.
- Games land in the chosen location: internal storage, other storage or
  a Games folder.
- The hero keeps its action row clear of the playtime column.
2026-10-26 09:01:02 -04:00
Kurt Himebauch 9fc48515c1 feat(input): unify low latency mode (#1604) 2026-10-26 08:12:47 -04:00
Kurt Himebauch 63d1e4d61d feat(library): remember visibility and store order (#1591) 2026-10-26 07:44:07 -04:00
Kurt Himebauch fbb334263c fix(ui): restore continuous ambient motion (#1592) 2026-10-26 02:05:19 -04:00
Kurt Himebauch 3fd6b1f00d fix(ui): restore consistent focus glide transitions (#1588) 2026-10-25 23:20:57 -04:00
Kurt Himebauch 5978a13f09 fix(stores): restore store capabilities in Library (#1586) 2026-10-25 22:07:42 -04:00
DrummingBird1 cce742766d fix: zero-copy launch log no longer points at a drawer switch that do… (#1354)
fix: describe the actual HDR zero-copy launch policy
2026-10-25 19:25:31 -04:00
Thomas Lee 4922d309c8 perf: allocate only solved DD-FG flow levels (#1556)
The flow solver starts at flowFinest_, but its images, uniform buffers and descriptor sets were allocated for every pyramid level. Keep the seven-level indices and allocate flow resources only where the solver reads and writes them.

The default preset avoids three unused RGBA16F images, saving 38,707,200 bytes of pixel payload at 2560x1440 without changing the shaders or recorded GPU work. Add native allocation/dispatch regressions and document the resource budgets.
2026-10-25 19:21:40 -04:00
MaxsTechReview 71fee6b3cc Keep a still direct touch held unless Long press is on (#1578) 2026-10-25 18:32:28 -04:00
Kurt Himebauch 4e00b40333 fix: start the session even when the agent environment can't be prepared (#1579) 2026-10-25 17:57:52 -04:00
Kurt Himebauch 65bacc067b fix: extract GOG installer fallback natively on ARM (#1174) 2026-10-25 17:56:35 -04:00
Kurt Himebauch 53ac21b4d0 fix: keep pending agent entries until the session's environment is ready 2026-10-25 17:50:51 -04:00
e76489ccea fix: refuse overwriting in-use component packages and clear unpacked store on replace (#1144)
* fix: refuse overwriting in-use component packages and clear unpacked store on replace

* fix: preserve component store until replacement succeeds

* fix: invalidate completed component cache before replace

* fix: constrain unpacked component cache path

* Test rejected package cache dot segments

---------

Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
2026-10-25 17:50:03 -04:00
ovurrsl 007166753c fix: start the session even when the agent environment can't be prepared 2026-10-25 17:35:36 -04:00
Kurt Himebauch 02767b7e6c fix: report a full battery at 100% while charging, so Steam stops showing 99% (#1577)
* fix: report a full battery at 100% while charging, so Steam stops showing 99%

* test: charging at 100% is reported full
2026-10-25 17:29:43 -04:00
cf13762939 feat: Show the drawer's game settings when a game starts without Steam (#1113)
* feat: Show the drawer's game settings when a game starts without Steam

A session started without the client has no Steam overview to read the
current title from, so the drawer's game profile group stayed empty and the
per-game settings, FEX preset, environment and unfolded controls were hidden.
The launch already knows which game it starts, so carry its id into the
session and fall back to it when Steam has nothing to report.

* fix: Pass the game id into the service start, and keep the unfolded toggle to Steam

SessionActivity.surfaceCreated() hands the mode, program and args to
SessionService.start(), which builds the service intent. EXTRA_GAME_ID was
only put on the activity intent, so a new no-Steam session never received it
and the drawer fallback stayed empty. Pass it through.

The unfolded-controls toggle also went out for direct sessions, but
applyUnfoldedControls() still requires Steam mode and a Deck pad, neither of
which a direct session sets up. Keep the toggle to Steam.

* fix: hide Steam controls in direct session drawer

---------

Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
2026-10-25 17:29:39 -04:00
kingokksa 9f4794769c feat: on-screen keys for any key or key combo (#1305) 2026-10-25 17:27:07 -04:00
6e67dbb5be fix: chosen game art survives a Steam account switch or runtime reset (#1026)
Every grid-<slot> record held only a file signature, not which grid
folder it came from. After switching accounts or reinstalling the
runtime, the new, empty grid folder looked like the user removed every
image in Steam, and all chosen art was deleted. The grid folder now
carries a random id and records store it; a record from another folder
counts as a first look, so the choice is placed again.

fix: never accept a record made with the fallback grid id

CodeRabbit: when the grid id could not be read or written, "?" was
stored in records and a later "?" matched it, so an empty grid could
still delete local art. Records now never match the fallback id, and a
blank .droiddeck-grid file is replaced instead of blocking the rename.

Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
2026-10-25 17:18:31 -04:00
19c655bd7e fix: update status receiver only acts on DroidDeck's own install session (#1015)
* fix: the update status receiver only acts on this app's own install session

Before Android 13 the receiver was exported, so any app could send a
fake PENDING_USER_ACTION broadcast and have DroidDeck launch an arbitrary
intent. The receiver now ignores broadcasts whose session id does not
match the running install, launches only a system installer activity,
and strips URI grant flags.

* fix: record the install session id before committing it

CodeRabbit: the status broadcast could arrive between commit() and
install() returning, while session was still -1, and be dropped. The id
is now reported through a callback before commit, and reset to -1 at
the start of each attempt so a late broadcast from an earlier session
is ignored.

* fix: declare package installer confirmation query

* Query current PackageInstaller confirmation action

---------

Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
2026-10-25 17:03:25 -04:00
Kurt Himebauch 815b93db5f feat: profile PRoot costs and test fast-path libraries without an APK rebuild (#1528) 2026-10-25 16:49:35 -04:00