Skip to content

Implement controller monitoring on Windows and fix Windows CI - #519

Merged
thp merged 6 commits into
thp:masterfrom
adangert:windows-monitor
Jul 30, 2026
Merged

Implement controller monitoring on Windows and fix Windows CI#519
thp merged 6 commits into
thp:masterfrom
adangert:windows-monitor

Conversation

@adangert

@adangert adangert commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Dynamic controller monitoring was added for Linux and macOS in previous commits. Windows did not have a moved_monitor implementation, so this functionality was disabled. This PR adds a Windows monitor using device notifications and periodic HID rescans, and fixes some issues with the Windows CI builds.

Implementation

  • Adds moved_monitor_windows.cpp
  • Registers for Windows device-interface notifications through CfgMgr32
  • Uses notifications to request an immediate HID rescan
  • Performs periodic rescans as a fallback when notifications are unavailable or missed
  • Detects both ZCM1 and ZCM2 controllers
  • Handles the multiple HID collections exposed for each controller on Windows
  • Uses case-insensitive device-path comparisons on Windows
  • Enables monitor construction, polling, and cleanup in PSMoveAPI on Windows
  • Pins Windows CI to windows-2022, the build currently targets Visual Studio 2022, and breaks with windows-latest which pulls in Visual Studio 2026
  • Restores the PS3Eye MSVC build by including winsock2.h; newer libusb headers no longer supply the timeval definition that PS3EYEDriver relied on

The monitor reports controller additions and removals through the same moved_monitor interface already used on Linux and macOS.

Testing

  • Built successfully with Visual Studio 2022 x64 in Debug and Release
  • Tested USB controller connection and pairing while the API was running
  • Tested Bluetooth connection, removal, and reconnection without restarting the application
  • Tested with multiple ZCM1 and ZCM2 controllers
  • Tested through JoustMania's new Python ctypes integration on Windows 11

@adangert adangert changed the title Add Windows controller hotplug monitoring Implement controller monitoring on Windows Jul 23, 2026
@adangert adangert changed the title Implement controller monitoring on Windows Implement controller monitoring on Windows & Fix Windows CI Jul 23, 2026
@adangert adangert changed the title Implement controller monitoring on Windows & Fix Windows CI Implement controller monitoring on Windows and fix Windows CI Jul 23, 2026
@adangert
adangert marked this pull request as ready for review July 23, 2026 05:53
Comment thread src/daemon/moved_monitor_windows.cpp Outdated
Comment thread src/daemon/moved_monitor_windows.cpp Outdated
Comment thread src/daemon/moved_monitor_windows.cpp
Comment thread src/daemon/moved_monitor_windows.cpp Outdated
Comment thread src/daemon/moved_monitor_windows.cpp Outdated
Comment thread src/daemon/moved_monitor_windows.cpp
Comment thread src/daemon/moved_monitor_windows.cpp
@adangert

Copy link
Copy Markdown
Contributor Author

Cleaned up code and addressed comments, thanks for reviewing! Retested on Windows, pairing both controller types.

@adangert
adangert requested a review from thp July 28, 2026 05:38

@thp thp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments. Getting there!

Also update CHANGELOG.md with the new feature :)

Comment thread src/daemon/moved_monitor_windows.cpp
Comment thread src/daemon/moved_monitor_windows.cpp
Comment thread src/daemon/moved_monitor_windows.cpp
Comment thread src/daemon/moved_monitor_windows.cpp Outdated
Comment thread src/daemon/moved_monitor_windows.cpp Outdated


int
moved_monitor_get_fd(moved_monitor *)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at usages of this function, src/utils/psmovepair.c has:

int run_daemon()
{
#if defined(__linux) || defined(__APPLE__)
    moved_monitor *monitor = moved_monitor_new(on_monitor_update_pair, NULL);
    int monitor_fd = moved_monitor_get_fd(monitor);
    struct pollfd pfd;

    pfd.fd = monitor_fd;
    pfd.events = POLLIN;

    while (1) {
        if (poll(&pfd, 1, 0) > 0) {
            moved_monitor_poll(monitor);
        }
    }

    moved_monitor_free(monitor);
#else
    for(;;) {
        psmove_port_sleep_ms(5000);
        pair(NULL);
    }
#endif

    return 0;
}

Should we adjust this to take advantage of the new monitor code when using psmove pair -d on the command line? Rescanning every 5 seconds is also not bad, but having this work more proactively would be nice. Then again, we would really need this to support a kind of blocking moved_monitor_poll() to take RESCAN_INTERVAL_MS into account.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea of being more proactive, I've updated the code, psmove pair -d now blocks in moved_monitor_wait(), waking immediately when the device-notification callback signals a controller change. It still uses RESCAN_INTERVAL_MS as a fallback if Windows misses a notification, without the previous five-second pairing loop or busy polling. More proactive now. I've left out updating this for Linux and macOS until further testing.

Tested successfully on Windows with controller pairing of both move controller types.

@adangert
adangert requested a review from thp July 30, 2026 06:37

@thp thp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean and fine now - thanks for working on this!

I'll have a look at the macOS/Linux polling cleanup now and will open a separate PR.

@thp
thp merged commit e680139 into thp:master Jul 30, 2026
4 checks passed
@adangert
adangert deleted the windows-monitor branch July 30, 2026 07:10
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.

2 participants