Improve Steam Input handling and update documentation
Updated main.js to better manage Steam Input environment variables, explicitly initialize and shutdown Steam Input, and regularly pump Steam callbacks to ensure proper controller support. Enhanced README-STEAM.md with detailed instructions for configuring Steam Input on Windows, Linux, and Steam Deck, including guidance for software/app limitations and launch options.
This commit is contained in:
+35
-3
@@ -136,9 +136,17 @@ gamepadAPI.setDebug(true);
|
||||
If Steam is still applying mouse emulation:
|
||||
|
||||
1. **Configure Steam Input per-game** (most reliable fix):
|
||||
- In Steam, right-click Nebula → Properties → Controller
|
||||
- Set **"Override for Nebula"** to **"Disable Steam Input"**
|
||||
- This completely disables Steam's input emulation for this app
|
||||
- **Windows / Desktop Steam UI**:
|
||||
- Library → right-click Nebula → Properties → **Controller**
|
||||
- Set **"Override for Nebula"** to **"Disable Steam Input"**
|
||||
- **Steam Deck / SteamOS Gaming Mode**:
|
||||
- Open Nebula → press the Steam button → **Controller Settings** (or the controller icon)
|
||||
- Set the layout to a **Gamepad** template (not “Keyboard/Mouse”), or disable Steam Input if the toggle is available
|
||||
- This stops Steam from translating controller input into keyboard/mouse events (“Desktop Layout” behavior).
|
||||
|
||||
If you **don’t see a Controller tab** (common when the Steam entry is treated as an “application/tool”):
|
||||
- Use **Big Picture / Gaming Mode** and edit the **Controller Layout** for that specific entry.
|
||||
- Or change Steam’s global Desktop Layout: Steam → Settings → Controller → **Desktop Layout** → pick a gamepad-focused template or remove mouse/keyboard bindings.
|
||||
|
||||
2. **Verify gamepad polling is active**: Open DevTools (F12) and run `gamepadAPI.getState()` - check that `isPolling` is `true`
|
||||
3. **Check gamepad connection**: Run `gamepadAPI.getConnected()` to see detected gamepads
|
||||
@@ -148,6 +156,20 @@ If Steam is still applying mouse emulation:
|
||||
|
||||
### Steam Launch Options
|
||||
|
||||
#### Windows
|
||||
|
||||
The `VAR=value %command%` syntax does **not** work on Windows. Use the Steam UI instead:
|
||||
|
||||
1. **Library** → right-click Nebula → **Properties** → **Controller** → set to **"Disable Steam Input"**
|
||||
2. If no Controller tab exists, open Steam in **Big Picture Mode** → Nebula → **Manage Game** (gear) → **Controller Options** → **Disable Steam Input**
|
||||
|
||||
If you must use launch options on Windows, use this wrapper syntax:
|
||||
```bat
|
||||
cmd /c "set SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD=0 && %command%"
|
||||
```
|
||||
|
||||
#### Linux / SteamOS / Steam Deck
|
||||
|
||||
Add these to your Steam launch options (Right-click game → Properties → Launch Options):
|
||||
|
||||
```bash
|
||||
@@ -187,6 +209,16 @@ The solution is two-fold:
|
||||
1. **Environment variables** (`SDL_GAMECONTROLLER_*`) signal to Steam's SDL-based input layer early
|
||||
2. **Steam Input settings** ("Disable Steam Input") bypasses the emulation entirely
|
||||
|
||||
### Shipping Defaults (Steamworks “Software/App” limitation)
|
||||
|
||||
If your Steamworks package is categorized as **Software/Application**, Steamworks may not expose per-title Steam Input configuration the way it does for games.
|
||||
|
||||
In that case:
|
||||
- You generally **cannot force a global Steam Input toggle** for all users from Steamworks.
|
||||
- The practical, shippable approach is to (a) **consume controller input natively** (Nebula does this via early Gamepad API polling) so Steam Deck/Game Mode backs off Desktop emulation, and (b) provide user-facing guidance for disabling Steam Input / choosing a Gamepad layout.
|
||||
|
||||
If you need Steam Input defaults controlled centrally, the usual path is to ask Valve Partner Support to enable the relevant Steam Input configuration for your App ID, or to re-categorize the title where appropriate.
|
||||
|
||||
### Force Big Picture Mode
|
||||
|
||||
```bash
|
||||
|
||||
@@ -15,7 +15,10 @@ process.env.SDL_GAMECONTROLLERCONFIG = process.env.SDL_GAMECONTROLLERCONFIG || '
|
||||
|
||||
// Signal that this app handles gamepad input natively
|
||||
// This prevents Steam from applying mouse emulation in Game Mode
|
||||
process.env.SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD = '1';
|
||||
// IMPORTANT: set to 0 to avoid Steam's virtual gamepad layer when possible.
|
||||
// Forcing this to 1 can keep Steam virtualization/emulation active.
|
||||
process.env.SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD =
|
||||
process.env.SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD ?? '0';
|
||||
|
||||
// Prevent Steam from remapping the controller to keyboard/mouse
|
||||
// Setting to '1' tells Steam we want raw controller access
|
||||
@@ -26,9 +29,8 @@ process.env.SteamNoOverlayUIDrawing = process.env.SteamNoOverlayUIDrawing || '0'
|
||||
|
||||
// Tell Steam Input we're a native controller app
|
||||
// When STEAM_INPUT_ENABLE_VIRTUAL_GAMEPAD is 0, Steam won't virtualize the gamepad
|
||||
if (!process.env.STEAM_INPUT_ENABLE_VIRTUAL_GAMEPAD) {
|
||||
process.env.STEAM_INPUT_ENABLE_VIRTUAL_GAMEPAD = '0';
|
||||
}
|
||||
process.env.STEAM_INPUT_ENABLE_VIRTUAL_GAMEPAD =
|
||||
process.env.STEAM_INPUT_ENABLE_VIRTUAL_GAMEPAD ?? '0';
|
||||
|
||||
// Hint that this is a game/controller-focused app
|
||||
process.env.SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS = '1';
|
||||
@@ -48,10 +50,13 @@ process.env.SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS = '1';
|
||||
let steamworksClient = null;
|
||||
let steamworksInitialized = false;
|
||||
let steamInput = null;
|
||||
let steamworksModule = null;
|
||||
let steamCallbacksInterval = null;
|
||||
|
||||
function initializeSteamworks() {
|
||||
try {
|
||||
const steamworks = require('steamworks.js');
|
||||
steamworksModule = steamworks;
|
||||
|
||||
// Initialize with Nebula's Steam App ID
|
||||
steamworksClient = steamworks.init(4290110);
|
||||
@@ -68,6 +73,27 @@ function initializeSteamworks() {
|
||||
if (steamInput) {
|
||||
console.log('[Steamworks] Steam Input API available - native controller mode enabled');
|
||||
|
||||
// Explicitly initialize Steam Input.
|
||||
// Also ensure Steam callbacks are pumped; Steamworks features (including input)
|
||||
// depend on runCallbacks being called regularly.
|
||||
try {
|
||||
if (typeof steamInput.init === 'function') {
|
||||
steamInput.init();
|
||||
}
|
||||
} catch (initErr) {
|
||||
console.log('[Steamworks] Steam Input init failed:', initErr.message);
|
||||
}
|
||||
|
||||
if (!steamCallbacksInterval && typeof steamworks.runCallbacks === 'function') {
|
||||
steamCallbacksInterval = setInterval(() => {
|
||||
try {
|
||||
steamworks.runCallbacks();
|
||||
} catch {
|
||||
// Ignore callback pump errors to avoid crashing the app.
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Try to get connected controllers to verify input is working
|
||||
try {
|
||||
const controllers = steamInput.getControllers();
|
||||
@@ -101,6 +127,19 @@ function initializeSteamworks() {
|
||||
// This is critical for Steam Input to recognize native controller support
|
||||
initializeSteamworks();
|
||||
|
||||
// Cleanup Steam callback pump on exit
|
||||
try {
|
||||
app?.once?.('before-quit', () => {
|
||||
if (steamCallbacksInterval) {
|
||||
clearInterval(steamCallbacksInterval);
|
||||
steamCallbacksInterval = null;
|
||||
}
|
||||
try {
|
||||
steamInput?.shutdown?.();
|
||||
} catch {}
|
||||
});
|
||||
} catch {}
|
||||
|
||||
const { app, BrowserWindow, ipcMain, session, screen, shell, dialog, Menu, clipboard, webContents } = require('electron');
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
const { pathToFileURL } = require('url');
|
||||
|
||||
Reference in New Issue
Block a user