Skip to content

fix(device): watch every idle receiver so mice reconnect after a KVM switch - #185

Open
mmaher88 wants to merge 1 commit into
masterfrom
fix/watch-every-idle-receiver
Open

mmaher88 wants to merge 1 commit into
masterfrom
fix/watch-every-idle-receiver

Conversation

@mmaher88

Copy link
Copy Markdown
Owner

Summary

Mice on Bolt receivers sometimes weren't set up again after switching a KVM back.

A receiver whose slot pings all fail (no mouse linked yet) is kept open until a mouse links up on it, and is then probed again. DeviceManager could hold only one such receiver (m_receiverDevice / m_receiverNotifier). With two receivers, both can come back from a KVM switch before either mouse has linked. When that happens, the second receiver replaces the first, so the first receiver's mouse is never set up again.

Seen on hardware: two Bolt receivers came back at the same moment, both had no mouse linked yet, and the running app had only one of them open. The MX Master 3S For Business stayed unconfigured until the app was restarted.

Change

  • One watch per receiver: idle receivers are now stored in a map keyed by device path (m_idleReceivers), each with its own socket notifier, so several can wait at once.
  • A mouse linking up re-probes only its own receiver; the other receivers keep waiting.
  • A receiver that goes away stops being watched, whether it becomes unreadable or udev removes it.
  • Safe notifier cleanup: the notifier is disabled before its file is closed and deleted only after its own signal has returned. The old code deleted it while its signal was still being delivered.

Tests

  • New test_idle_receivers.cpp: pipes stand in for two receivers. With the old one-receiver behaviour put back, 4 of its 5 tests fail.
  • DeviceRegistry.ReloadByPathRefreshesSingleDevice: this test only passed if it ran before any test that calls ensureApp(). ensureApp() switches Qt into a test mode that ignores XDG_DATA_HOME, which this test relies on. The test now turns that mode off for its own duration and restores it afterwards. The comment in test_action_filter_model.cpp that described working around this is updated.
  • Results: C++ 899/899 (three runs), QML 72/72, pre-push hook passed.
  • Hardware (MX Master 3S + MX Master 3S For Business, each on its own Bolt receiver):
    • After a KVM round trip, the For Business's receiver came back with no mouse linked, was kept open, and the mouse was set up again 1.3 s later.
    • The 3S being turned on was picked up the same way through its own receiver.
    • The app ended up with both receivers open.

🤖 Generated with Claude Code

…switch

A receiver whose slot pings all fail is kept open until a mouse links
up on it. DeviceManager held a single such receiver, so when two came
back with no mouse linked yet (both receivers returning together after
a KVM switch), the second one replaced the first and the first mouse
was never set up again.

Idle receivers are now tracked per devNode. Data on one re-probes only
that receiver; a receiver that goes away (unreadable or udev remove)
stops being watched.

Tests: test_idle_receivers.cpp drives the watch with pipes standing in
for two receivers. DeviceRegistry.ReloadByPathRefreshesSingleDevice no
longer depends on running before any test that calls ensureApp(): it
turns QStandardPaths test mode off for its duration and restores it.
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