为什么 CGWarpMouseCursorPosition 会导致延迟?如果不是,那是什么?

发布于 2024-12-17 09:43:56 字数 2299 浏览 2 评论 0原文

我这里有代码将鼠标限制在屏幕上的某个区域,它工作得相对良好,只有一个大问题。当沿着区域边缘运行时,鼠标不会干净/平滑地移动,而是以一种非常不稳定的方式跳跃,我相信这可能是由于 CGWarpMouseCursorPosition 导致每次“扭曲”延迟。

谁能告诉我是否是我的代码中的某些内容导致了这种延迟,或者实际上是鼠标扭曲功能。如果是鼠标扭曲功能,有什么方法可以平滑地重新定位鼠标吗?我在Flash中做了同样的事情,它工作完美,我知道循环不只是采取执行时间太长,导致速度减慢,因为它可能只运行 4 或 5 次。

CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {


    CGPoint point = CGEventGetLocation(event);

    float tX = point.x;
    float tY = point.y;

    if( tX <= 700 && tX >= 500 && tY <= 800 && tY >= 200){
        // target is inside O.K. area, do nothing
    }else{

    CGPoint target; 

    //point inside restricted region:
    float iX = 600; // inside x
    float iY = 500; // inside y

    // delta to midpoint between iX,iY and tX,tY
    float dX;
    float dY;

    float accuracy = .5; //accuracy to loop until reached

    do {
        dX = (tX-iX)/2;
        dY = (tY-iY)/2;

        if((tX-dX) <= 700 && (tX-dX) >= 500 && (tY-dY) <= 800 && (tY-dY) >= 200){
            iX += dX;
            iY += dY;
        } else {
            tX -= dX;
            tY -= dY;
        }

    } while (abs(dX)>accuracy || abs(dY)>accuracy);

        target = CGPointMake(roundf(tX), roundf(tY));
        CGWarpMouseCursorPosition(target);

    }



    return event;
}

int
main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    CFRunLoopSourceRef runLoopSource;
    CGEventMask event_mask;
    event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged);

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, NULL);

    if (!eventTap) {
        NSLog(@"Couldn't create event tap!");
        exit(1);
    }

    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(eventTap, true);

    CFRunLoopRun();

    CFRelease(eventTap);
    CFRelease(runLoopSource);
    [pool release];

    exit(0);
}

I have code here that restricts the mouse to a region on the screen, it is working relatively well, with only one big problem. The mouse doesn't get moved cleanly/smoothly when running along the edges of the area, it instead jumps in a very choppy manner, I believe this might be due to CGWarpMouseCursorPosition causing a delay upon each "warp".

Can anyone tell if it's something in my code that is causing this delay, or if it is in fact the mouse warp function. If it is the mouse warp function, is there any way I can get a smooth relocation of the mouse? I've done the same thing in flash and it works flawlessly, I know that the loop isn't just taking so much time to execute that it's slowing things down because it only runs maybe 4 or 5 times.

CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {


    CGPoint point = CGEventGetLocation(event);

    float tX = point.x;
    float tY = point.y;

    if( tX <= 700 && tX >= 500 && tY <= 800 && tY >= 200){
        // target is inside O.K. area, do nothing
    }else{

    CGPoint target; 

    //point inside restricted region:
    float iX = 600; // inside x
    float iY = 500; // inside y

    // delta to midpoint between iX,iY and tX,tY
    float dX;
    float dY;

    float accuracy = .5; //accuracy to loop until reached

    do {
        dX = (tX-iX)/2;
        dY = (tY-iY)/2;

        if((tX-dX) <= 700 && (tX-dX) >= 500 && (tY-dY) <= 800 && (tY-dY) >= 200){
            iX += dX;
            iY += dY;
        } else {
            tX -= dX;
            tY -= dY;
        }

    } while (abs(dX)>accuracy || abs(dY)>accuracy);

        target = CGPointMake(roundf(tX), roundf(tY));
        CGWarpMouseCursorPosition(target);

    }



    return event;
}

int
main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    CFRunLoopSourceRef runLoopSource;
    CGEventMask event_mask;
    event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged);

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, NULL);

    if (!eventTap) {
        NSLog(@"Couldn't create event tap!");
        exit(1);
    }

    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(eventTap, true);

    CFRunLoopRun();

    CFRelease(eventTap);
    CFRelease(runLoopSource);
    [pool release];

    exit(0);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寒江雪… 2024-12-24 09:43:56

正如您所发现的,CGSetLocalEventsSuppressionInterval 解决了您的问题。

但是,从 10.6 开始它已被弃用。苹果文档指出:

由于未记录的特殊情况和不良副作用,不建议将此函数用于一般用途。建议替换此函数的是 CGEventSourceSetLocalEventsSuppressionInterval,它允许针对特定事件源调整抑制间隔,仅影响使用该事件源发布的事件。

不幸的是,替换CGEventSourceSetLocalEventsSuppressionInterval不适用于CGWarpMouseCursorPosition移动。

相反,在扭曲之后立即使用 CGAssociateMouseAndMouseCursorPosition(true):

CGPoint warpPoint = CGPointMake(42, 42);
CGWarpMouseCursorPosition(warpPoint);
CGAssociateMouseAndMouseCursorPosition(true);

文档没有提及此行为,但它似乎取消了扭曲之后的抑制间隔。

As you discovered, CGSetLocalEventsSuppressionInterval fixes your problem.

However, it's deprecated as of 10.6. the Apple docs state:

This function is not recommended for general use because of undocumented special cases and undesirable side effects. The recommended replacement for this function is CGEventSourceSetLocalEventsSuppressionInterval, which allows the suppression interval to be adjusted for a specific event source, affecting only events posted using that event source.

Unfortunately, the replacementCGEventSourceSetLocalEventsSuppressionInterval does not work with CGWarpMouseCursorPosition movements.

Instead, use CGAssociateMouseAndMouseCursorPosition(true) immediately after the warp:

CGPoint warpPoint = CGPointMake(42, 42);
CGWarpMouseCursorPosition(warpPoint);
CGAssociateMouseAndMouseCursorPosition(true);

The documentation makes no mention of this behavior, but it appears to cancel the suppression interval after the warp.

暮倦 2024-12-24 09:43:56

我可以通过以下方式让 CGEventSourceSetLocalEventsSuppressionIntervalCGWarpMouseCursorPosition 一起使用:

auto eventSourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventSourceSetLocalEventsSuppressionInterval(eventSourceRef, 0);

这可以很好地与 CGWarpMouseCursorPosition 配合使用(并且未弃用),而 CGAssociateMouseAndMouseCursorPosition (true) 对我没有帮助。

I could get CGEventSourceSetLocalEventsSuppressionInterval to work with CGWarpMouseCursorPosition the following way:

auto eventSourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventSourceSetLocalEventsSuppressionInterval(eventSourceRef, 0);

This works fine with CGWarpMouseCursorPosition (and is not deprecated), whereas CGAssociateMouseAndMouseCursorPosition(true) was of no help for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文