问题
I have a global app that prevents the mouse from moving into areas of the screen. Must work with all apps, while my app in the background, etc.
I have set up a CGEventTap
hook that has a callback for mouse movements.
The user's mouse movement continues to pass through the hook, no matter how I attempt to modify/kill the movement. That mirrors the experiences of others: https://stackoverflow.com/a/5831573/106761
- (CGEventRef) mouseMovedEvent:(CGEventRef) newUserMouseMovement
{
//Attempt to modify the mouse movement
CGEventSetDoubleValueField(newUserMouseMovement, kCGMouseEventDeltaX, 0);
CGEventSetDoubleValueField(newUserMouseMovement, kCGMouseEventDeltaY, 0);
CGEventSetDoubleValueField(newUserMouseMovement, kCGMouseEventDeltaX, 0.0);
//Attempt to kill the event
return NULL;
}
//Mouse movement still works normally.
I am able to use CGDisplayMoveCursorToPoint
or CGWarpMouseCursorPosition
to reposition the cursor back to the original position.
This works fine, although I would rather just kill the event altogether.
The problem is that the original user mouse movement shows the cursor visual at that point for a split second, before I am able to move the cursor.
I'm using:
CGSetLocalEventsSuppressionInterval(0.0);
to increase the frequency at which the Mouse movement fires. But that also makes the "real" cursor, before I move it, flash in the "forbidden area" if the user holds the mouse against the area in which I don't want the mouse to go.
I will potentially use: Globally hiding cursor (from background app) but I doubt that would be Mac App Store legal.
Any ideas?
EDIT: How I create the event tap:
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL);
...
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
{
if (type == kCGEventMouseMoved) {
event = [refToSelf mouseMovedEvent:event];
}
...
return event;
}
回答1:
You're trying to modify events at the kCGHIDEventTap location, which
Specifies that an event tap is placed at the point where HID system events enter the window server.
Unfortunately, the CGEventTapCreate() doc says:
Only processes running as the root user may locate an event tap at the point where HID events enter the window server; for other users, this function returns
NULL
.
I suspect this is strongly related to your difficulty, although the docs don't seem to match up with exactly what's happening (they are more than four years old).
Perhaps you can spin this functionality off into a separate process that has super-user permissions, leaving the rest of your app in normal user mode? I believe there's also a way to request root permissions for just a specific action taken by your program.
来源:https://stackoverflow.com/questions/9899534/prevent-mousemovedevent-callback-from-processing-the-movement-or-globally-hid