Releases: twolven/mousebridge
Release list
v1.0.3 — focus gate fix (Explorer's invisible switcher windows)
Agent-only release. The relay and Pi pump are unchanged from v1.0.2 — the .exes and installer scripts are re-attached here so this release is a complete install on its own.
The bug
The mouse bridge would refuse to activate even though the Moonlight window was plainly focused. Alt-tabbing away and back fixed it every time.
The culprit turned out to be Explorer, not Moonlight. Every alt-tab or taskbar click pushes 3–4 invisible, titleless explorer.exe windows (the task switcher) through the foreground for a frame. The agent read each one as "focus left the stream window", gated off — and then no event ever arrived to turn it back on, because focus never actually moved. The stream stayed dead until the next real window switch.
Log signature, in the same second:
Focus GAINED -> streaming to ...
Focus LOST -> stream stopped (1 packets, 0 send errors, 0.0min session)
Running two Moonlight instances doubles the hidden helper windows and makes it frequent.
A second defect surfaced during the fix: the foreground event for the real destination window is sometimes never delivered at all, which can strand the gate in either state.
The fix
- Invisible windows — and titleless windows belonging to the stream window's own process — can no longer move the gate. Both are logged with hwnd + pid.
- 200 ms foreground reconciliation riding the existing keepalive timer: the gate is re-checked against the real foreground window and self-heals any disagreement, whatever caused it. Worst case is 200 ms of dead mouse instead of a dead session.
- The gate latches the stream window's hwnd/pid, so only the foreground window drives it. A duplicate window with the same title logs a
[WARN]naming the extra pid instead of fighting over the gate. - 64-bit correctness:
argtypesforGetWindowText*/GetWindowThreadProcessId/IsWindowVisibleso HWNDs aren't truncated to 32 bits.
Upgrading
Replace mousebridge-agent.exe in %USERPROFILE%\MouseBridge and restart it — kill the start-agent.cmd wrapper loop first, or it will respawn onto the locked file. Config and the relay need no changes.
v1.0.2 — drag-and-drop fix
Fixed
- Drag-and-drop released after ~2s: the relay's Pi-health probe (sent every 2s with
buttons=0) was written to the HID as real input, force-releasing any held button. The pump now treats probes (seq0xFFFE) as echo-only — they never touch HID state or the seq-gap loss stats (which they were also polluting with fake 25–53% loss spikes). - Click grace fired the press late mid-drag: the v1.0.1 focus click-grace masked all buttons by time, so a click-drag started as the streaming window gained focus sent its press 300ms late, mid-motion. Grace now suppresses only the focus-gaining press itself, until its own physical release.
Changed
- Pump failsafe 0.3s → 1.0s (real streams showed 456ms keepalive gaps; failsafe is crash-safety only — the agent releases explicitly on focus loss).
- Button diagnostics on both ends: holds ≥300ms log their duration on release (agent + pump), suppressed presses and mid-hold focus theft are logged with the stealing window's title.
start-agent.cmduses the full exe path (bare-name cwd lookup breaks underNoDefaultCurrentDirectoryInExePath).
Updating
- Local PC: replace
mousebridge-agent.exeandstart-agent.cmdin%USERPROFILE%\MouseBridge(stop the agent + its wrapper loop first). - Pi: rerun the installer (or copy
pi/hidpump.pyto/opt/mousebridge/) andsudo systemctl restart hidpump. - Relay (remote PC): unchanged — v1.0.1 relay works as-is.
Also in this build
- Agent: fractional carry for high-res/free-spin wheel deltas (floor division dropped sub-notch up-scrolls and over-fired down-scrolls; commit e5beacb).
MouseBridge v1.0.1
Field fixes from the first day of real use:
- Double-click fix (pump): bounded-wait HID writes instead of dropping when 1kHz packets outpace the host poll — dropped button transitions broke double-clicks
- Focus click-grace (agent): the click that focuses the streaming window no longer fires remotely (
CLICK_GRACE_MS, default 300) - Live tuning (agent):
SCALEandCLICK_GRACE_MShot-reload from config.txt while running - Kill hotkey: relay config now documents arming it (
KILL_PROCESS/KILL_KEY) - Installer targets
%USERPROFILE%\MouseBridge(migrates oldC:\MouseBridge) - Relay: tray icon with Exit, windowless build, single-instance, self-restart
- If you stream the desktop, set
mouse = disabledin Sunshine so simulated clicks don't interleave with the bridge's hardware clicks
MouseBridge v1.0.0
First stable release — fully replaces VirtualHere for Moonlight/Sunshine mouse passthrough.
Measured full-path latency: 0.70 ms median round-trip, 0 loss in 5,000 probes. Focus switching: <5 ms (vs 1.5-3.5 s USB re-enumeration with VirtualHere).
Assets:
mousebridge-agent.exe— local PC (Moonlight side); self-contained, no Python neededmousebridge-relay.exe— remote PC (Sunshine host); windowless tray app with green/red status overlayinstall-relay.cmd+start-relay.cmd— remote PC installer (put next to the relay exe, double-click)start-agent.cmd— local PC launcher/autostart script
Pi side: clone the repo on the Pi and sudo bash pi/install.sh. Full instructions in the README.