Reputation: 2659
I am trying to detect mouse events along with device details on macos. The code detects external mouse events but doesn't detect internal trackpad events. Surprisingly the same code works on
It doesn't work on
Code
#include <iostream>
#include <IOKit/hid/IOHIDManager.h>
#include <CoreFoundation/CoreFoundation.h>
void mouseEventCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
std::cout << "Mouse event" << std::endl; // Prints only external mouse events. Doesn't work for internal trackpad.
}
int main() {
IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
// Create a matching dictionary for mouse and trackpad devices
CFMutableDictionaryRef matchingDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Add matching criteria for mouse and trackpad devices
CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDDeviceUsagePageKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, (const int[]){1})); // Generic Desktop Controls
CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDDeviceUsageKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, (const int[]){2, 5})); // Mouse, Touchpad
// Set the matching criteria
IOHIDManagerSetDeviceMatching(manager, matchingDict);
// Register the callback for input value changes
IOHIDManagerRegisterInputValueCallback(manager, mouseEventCallback, NULL);
// Open the HID manager
IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
// Schedule the HID manager with the current run loop
IOHIDManagerScheduleWithRunLoop(manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
// Run the loop to listen for events
CFRunLoopRun();
// Clean up
CFRelease(matchingDict);
CFRelease(manager);
return 0;
}
Compile command
clang++ -o mouse mouse.cpp -framework IOKit -framework CoreFoundation
I have also tried external libs like https://github.com/icculus/manymouse but the same issue persists.
Also, when I use IOHIDManagerRegisterDeviceMatchingCallback
both external mouse and trackpad gets registerd but the events are not detected from the internal trackpad.
I tried using CGEventTapCreate which detects events from both trackpad and external mouse on all devices but, I can't use it as it doesn't give device details along with events (Product id, vendor id etc).
// This works
#include <iostream>
#include <ApplicationServices/ApplicationServices.h>
// Event tap callback function
CGEventRef eventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* userInfo) {
if (type == kCGEventLeftMouseDown || type == kCGEventRightMouseDown || type == kCGEventOtherMouseDown) {
CGPoint mouseLocation = CGEventGetLocation(event);
std::cout << "Mouse Clicked at: (" << mouseLocation.x << ", " << mouseLocation.y << ")" << std::endl;
}
else if (type == kCGEventScrollWheel) {
// For scroll events
CGPoint scrollDelta = CGEventGetUnflippedLocation(event);
std::cout << "Mouse Scrolled at: (" << scrollDelta.x << ", " << scrollDelta.y << ")" << std::endl;
}
return event;
}
int main() {
// Create an event tap to monitor mouse events
CGEventMask eventMask = CGEventMaskBit(kCGEventLeftMouseDown) |
CGEventMaskBit(kCGEventRightMouseDown) |
CGEventMaskBit(kCGEventOtherMouseDown) |
CGEventMaskBit(kCGEventScrollWheel);
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, eventMask, eventTapCallback, nullptr);
if (!eventTap) {
std::cerr << "Failed to create event tap." << std::endl;
return 1;
}
// Create a run loop source and add it to the current run loop
CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CFRelease(runLoopSource);
// Enable the event tap
CGEventTapEnable(eventTap, true);
// Run the run loop to process events
CFRunLoopRun();
return 0;
}
Upvotes: 2
Views: 78