diff --git a/docs/macos-gamepad.md b/docs/macos-gamepad.md index 00c8700..f2d4ad1 100644 --- a/docs/macos-gamepad.md +++ b/docs/macos-gamepad.md @@ -5,6 +5,13 @@ root-owned broker. The broker alone calls Apple's `IOHIDUserDevice` API and hold the virtual HID entitlement. The ordinary C++ library has no Apple entitlement and uses CoreGraphics for keyboard and mouse input. +The broker's gamepad report thread and `IOHIDUserDevice` callback queue request +user-interactive QoS to reduce scheduling delay in the input path. License +validation and other broker work keep their normal scheduling. This is a +best-effort priority hint, not a real-time latency guarantee. The virtual HID +device is provided by macOS, so there is no separate libvirtualhid driver +process to prioritize. + The client checks root ownership of the broker directory, socket, and connected peer before exchanging versioned messages. Socket transfers handle partial reads and writes so truncated messages are not treated as complete. diff --git a/src/platform/macos/broker/libvirtualhid_macos_broker.cpp b/src/platform/macos/broker/libvirtualhid_macos_broker.cpp index 06d418b..34d5fce 100644 --- a/src/platform/macos/broker/libvirtualhid_macos_broker.cpp +++ b/src/platform/macos/broker/libvirtualhid_macos_broker.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -263,7 +264,7 @@ namespace lvh::detail::macos_broker { *size = static_cast(report.size()); return kIOReturnSuccess; }); - IOHIDUserDeviceSetDispatchQueue(device, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)); + IOHIDUserDeviceSetDispatchQueue(device, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)); IOHIDUserDeviceSetCancelHandler(device, ^{ dispatch_semaphore_signal(cancelled); }); @@ -276,6 +277,8 @@ namespace lvh::detail::macos_broker { } void receive_reports(DeviceSession &session, LicenseManager &licenses, bool evaluation, std::uint32_t expected_input_size) { + // Only the HID input path needs interactive scheduling; licensing stays at its normal QoS. + static_cast(::pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0)); Message request; for (;;) { pollfd descriptor {.fd = session.fd, .events = POLLIN, .revents = 0};