Skip to content

feat(frontend,installer): map the controller to keyboard and mouse with a Workshop layout - #5

Merged
dangreen merged 1 commit into
mainfrom
feat/controller-layout
Oct 21, 2026
Merged

dangreen merged 1 commit into
mainfrom
feat/controller-layout

Conversation

@dangreen

Copy link
Copy Markdown
Member

Why

Feedback from a player: of the games added, only Myst worked with the controller out of the box. Syberia wanted a real mouse, and in Deus Ex the controller could turn, switch weapons and fire, but not walk. A game made for keyboard and mouse needs a layout that maps the controller to them. Steam keeps one per game and controller type, and community layouts come from the Workshop (SPEC 7.8).

What

Site

  • A new section, Controller, after Artwork. It starts with a box, off by default: "Map the controller to keyboard and mouse". A game that supports a controller needs nothing.
  • Ticked, the box shows a field for a link to a layout, with a link that searches SteamInputDB for the title. getLayoutId takes the ID out of steaminputdb.com/config/<ID> or a bare ID, and anything else is marked in the field with an example of a right link. Neither Steam nor SteamInputDB answers a page on another site, so the link is all there is to go by.
  • The ID goes into recipe.json as controller_layout, null with the box off. With the box ticked, the build waits for a layout. Another archive unticks the box and empties the field.
  • steamGridDbUrl is renamed getSteamGridDbUrl: functions of services start with a verb.

Installer

  • While Steam is still up, it asks ISteamRemoteStorage/GetPublishedFileDetails, which needs no key, which controller the layout is made for: the layout's controller_* tag.
  • With Steam down, it backs up configset_controller_<type>.vdf and writes "workshop" "<ID>" for the game into it, keyed by the game's name the way Steam keys shortcuts. After the restart it checks that the entry is still there. A missing entry is logged and shown, not retried: a layout is no reason to restart Steam once more.
  • Without a connection, or with an ID that is not a layout, the game installs all the same, and the last window says the layout was not set. install.py writes such things as NOTE: lines, and setup.sh adds them to the window.
  • The uninstaller takes the entry out of every controller's file where it still points at that layout, backing the file up first.
  • --purge also removes the game's shadercache/<appid> and the <slug> folder once nothing else is in it. Both were left behind after every purge on a Deck and had to be deleted by hand.

Verified on a Deck

SteamOS 3.8.28 in Desktop Mode, with Deus Ex Revision and the layout 3037080160 (controller_neptune), built into a .run with this installer:

  • Installed on the first attempt. The log says controller layout: 3037080160, made for controller_neptune, and after the restart controller layout: kept.
  • Steam fetched the layout by itself 16 s after it came back, into steamapps/workshop/content/241100/3037080160/, so the installer downloads nothing. The game played with the layout on its first launch.
  • --uninstall --purge removed the shortcut, Proton, the layout entry, the game folder and the prefix, and Steam's rewrite of shortcuts.vdf did not bring the shortcut back. The shader cache and the empty folder were then removed by hand: the --purge change above is covered by the self-test, not run on the Deck yet.

Notes

  • Frontend: lint, types and 664 tests pass. The installer self-test has 9 new checks, 72 in all, and passes; the checks for the uninstall changes fail on the code without them. editorconfig-checker finds no errors.
  • Still open (SPEC 7.8): whether Steam Input has to be turned on for the game with a controller other than the built-in one.
  • The site packs the installer into every .run it builds, so the installer part reaches a player once the site is deployed and the .run is built again.

…th a Workshop layout

A player could turn, switch weapons and fire in Deus Ex with the controller, but not walk: a game made for keyboard and mouse needs a layout that maps the controller to them, and Steam keeps one per game.

- The site gets a Controller section: a box, off by default, and once it is ticked a field for a link to a layout on SteamInputDB, next to a link that searches it for the title. The ID goes into recipe.json as controller_layout.
- The installer asks Steam which controller the layout is made for, writes "workshop" "<ID>" for the game into that controller's configset file while Steam is down, and checks it after the restart. Steam fetches the layout by itself, verified on a Deck. A layout that could not be set leaves the game installed, and the last window says so.
- The uninstaller takes the entry out, backing the file up first, and --purge also removes the game's shader cache and the emptied <slug> folder.
- steamGridDbUrl is getSteamGridDbUrl: functions of services start with a verb.
@dangreen
dangreen merged commit ad8d25a into main Oct 21, 2026
6 checks passed
@dangreen
dangreen deleted the feat/controller-layout branch October 21, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant