-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Setup
If you want to run or modify Mojo Input Manager from source, follow these steps.
- Node.js
- npm (included with Node.js)
- Windows (the app, and the vJoy/HidHide drivers it automates, are Windows-only)
- vJoy and HidHide installed, if you want to exercise those features rather than just the UI
git clone https://github.com/mojouto3/mojo-input-manager.git
cd mojo-input-managernpm installnpm run devThis runs Vite (renderer, with hot module reload) and Electron together. DevTools open automatically in dev mode.
Note: Files with a
requestAnimationFrameloop, currentlyMapping.jsx, have occasionally shown stale-closure symptoms under hot reload (old code keeps running after a save). If Mapping behaves unexpectedly after an edit, do a full restart (stop the dev server, kill any lingeringelectron.exe, runnpm run devagain) rather than trusting HMR.
npm run distBuilds the renderer and packages a Windows NSIS installer into release/. Use npm run dist:dir for an unpacked build (faster, useful for quick manual testing without the installer step).
npm run dist -- --publish=alwaysRequires a GH_TOKEN environment variable with permission to upload release assets. This builds, then uploads the installer and update metadata (latest.yml, block map) to a GitHub Release, which is what the auto-updater checks against.
mojo-input-manager/
├── assets/ Icons, logos, social preview
├── src/
│ ├── main/
│ │ ├── main.js Electron main process: window, tray, IPC, auto-updater
│ │ ├── vjoy.js vJoyConfig.exe wrapper (create/delete, elevated)
│ │ ├── vjoyInterface.js vJoyInterface.dll wrapper via koffi (live feed)
│ │ ├── hidhide.js HidHideCLI.exe wrapper (devices, cloak, apps)
│ │ ├── profiles.js Per-game device filtering profiles
│ │ └── mappingProfiles.js Remembered physical-device-to-vJoy mappings
│ └── renderer/
│ ├── preload.js contextBridge: the only surface the renderer can reach main through
│ ├── components/ Shared UI: Card, Button, Badge, Toggle, Select, Sidebar, TitleBar...
│ ├── theme.js Accent theme (green/cyan) persistence
│ └── views/ Dashboard, VirtualDevices, Mapping, DeviceFiltering, Settings
└── package.json
Notable implementation details:
-
vJoy:
vjoy.jsshells out tovJoyConfig.exefor create/delete (elevated via a UAC prompt, since those change persistent driver config), whilevjoyInterface.jscallsvJoyInterface.dlldirectly through koffi (FFI) for the actual live axis/button feed, which doesn't need elevation. -
HidHide:
hidhide.jsspawnsHidHideCLI.exewithstdio: ['ignore', 'pipe', 'pipe']rather than usingexecFile, because the CLI blocks waiting on stdin otherwise. Calls are also serialized through an internal queue, since the CLI doesn't tolerate concurrent invocations. - Physical device detection: done entirely through the browser's Gamepad API in the renderer, no native module needed just to see connected controllers.
-
Mapping: a
requestAnimationFrameloop inMapping.jsxpollsnavigator.getGamepads()and sends combined axis/button state to the main process over IPC, which feeds it into vJoy viavjoyInterface.js.
This project uses a two-account workflow:
| Account | Role |
|---|---|
mojouto3 |
Manager: repo administration, releases, milestones |
Constantinos-T |
Developer: feature branches, commits, opens PRs |
Both open PRs for their own contributions; the other reviews before merge (GitHub doesn't allow self-approval). All PRs target main and require 1 review. Branches are deleted after merging.
git checkout main
git pull origin main
git checkout -b your-feature-name- The
dist/(renderer build output) andrelease/(packaged installer) folders are gitignored, safe to delete, and recreated on every build. - The auto-updater only runs in packaged builds (
app.isPackaged). In dev mode it's a no-op, and the Settings tab reports "Only available in installed builds".