objective-c - 段错误 11 | CGEventTap 应用程序在任意时间后停止处理鼠标事件。

标签 objective-c macos cocoa core-graphics cgeventtap

此应用程序的目的是 24/7 在后台运行并将鼠标锁定在屏幕中央。它用于与一系列 Flash 程序一起模拟鼠标的操纵杆式移动。我已经尝试使用 Cocoa/Quartz 中内置的其他方法来完成此任务,但它们都没有达到我的目的,所以这就是我必须这样做的方式。

我一直试图找出为什么在看似随机的一段时间后,这个程序就停止限制鼠标。该程序不会给出错误或类似的信息,它只是停止工作。强制退出屏幕确实显示“未响应”,但是,我的许多鼠标修改脚本(包括这个脚本)总是显示为“未响应”,并且它们继续运行。

代码如下:

code removed, check below for updated code.

最终更新

Ken Thomases 给了我正确的答案,我已经根据他的建议更新了我的代码。 这是我完美运行的最终代码(在我手动停止它之前,它运行了 12 个多小时,没有出现任何问题):

#import <Cocoa/Cocoa.h>
#import <CoreMedia/CoreMedia.h>

int screen_width, screen_height;

struct event_tap_data_struct {
    CFMachPortRef event_tap;
    float speed_modifier;    
};

CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *);



int
screen_res(int);


int
main(int argc, char *argv[]) {



    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


    screen_width = screen_res(0);
    screen_height = screen_res(1);
    CFRunLoopSourceRef runLoopSource;
    CGEventMask event_mask = kCGEventMaskForAllEvents;

    CGSetLocalEventsSuppressionInterval(0);
    CFMachPortRef eventTap;
    struct event_tap_data_struct event_tap_data = {eventTap,0.2};

    eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data);
    event_tap_data.event_tap = eventTap;
    if (!eventTap) {
        NSLog(@"Couldn't create event tap!");
        exit(1); 
    }

    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_data.event_tap, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(event_tap_data.event_tap, true);

    CFRunLoopRun();

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

    exit(0);
}

int
screen_res(int width_or_height) {

    NSRect screenRect;
    NSArray *screenArray = [NSScreen screens];
    unsigned screenCount = (unsigned)[screenArray count];


    for (unsigned index  = 0; index < screenCount; index++)
    {
        NSScreen *screen = [screenArray objectAtIndex: index];
        screenRect = [screen visibleFrame];
    }
    int resolution_array[] = {(int)CGDisplayPixelsWide(CGMainDisplayID()),(int)CGDisplayPixelsHigh(CGMainDisplayID())};

    if(width_or_height==0){
        return resolution_array[0];
    }else {
        return resolution_array[1];

    }

}


CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *event_tap_data) {


    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    if (type == kCGEventTapDisabledByTimeout || type == kCGEventTapDisabledByUserInput) {

        CGEventTapEnable(event_tap_data->event_tap,true);
        return event;

    } else if (type == kCGEventMouseMoved || type == kCGEventLeftMouseDragged || type == kCGEventRightMouseDragged || type == kCGEventOtherMouseDragged){

    CGPoint point = CGEventGetLocation(event);
    NSPoint old_point;

    CGPoint target; 
    int tX = point.x; 
    int tY = point.y; 
    float oX = screen_width/2;
    float oY = screen_height/2;
    float dX = tX-oX;
    float dY = tY-oY;

    old_point.x = floor(oX); old_point.y = floor(oY);

    dX*=2, dY*=2;

    tX = round(oX + dX);
    tY = round(oY + dY);


    target = CGPointMake(tX, tY);


    CGWarpMouseCursorPosition(old_point);
    CGEventSetLocation(event,target);

    }

    [pool release];

    return event;
}

(第一)更新:

该程序仍然崩溃,但我现在已将其作为可执行文件运行并收到错误代码。

当它终止时,控制台会记录“段错误:11”。

我一直在试图找出这意味着什么,但它似乎是一个令人印象深刻的广泛术语,而且我还没有磨练出一些有用的东西。

这是我正在使用的新代码:

#import <Cocoa/Cocoa.h>
#import <CoreMedia/CoreMedia.h>

int screen_width, screen_height;

struct event_tap_data_struct {
    CFMachPortRef event_tap;
    float speed_modifier;    
};

CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *);



int
screen_res(int);


int
main(int argc, char *argv[]) {


    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


    screen_width = screen_res(0);
    screen_height = screen_res(1);
    CFRunLoopSourceRef runLoopSource;
    CGEventMask event_mask;
    event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged);

    CGSetLocalEventsSuppressionInterval(0);
    CFMachPortRef eventTap;
    CFMachPortRef *eventTapPtr = &eventTap;
    struct event_tap_data_struct event_tap_data = {*eventTapPtr,0.2};

    eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data);

    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);
}

int
screen_res(int width_or_height) {

    NSRect screenRect;
    NSArray *screenArray = [NSScreen screens];
    unsigned screenCount = (unsigned)[screenArray count];


    for (unsigned index  = 0; index < screenCount; index++)
    {
        NSScreen *screen = [screenArray objectAtIndex: index];
        screenRect = [screen visibleFrame];
    }
    int resolution_array[] = {(int)CGDisplayPixelsWide(CGMainDisplayID()),(int)CGDisplayPixelsHigh(CGMainDisplayID())};

    if(width_or_height==0){
        return resolution_array[0];
    }else {
        return resolution_array[1];

    }

}


CGEventRef 
mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *event_tap_data) {


    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    if (type == kCGEventTapDisabledByTimeout || type == kCGEventTapDisabledByUserInput) {

        CGEventTapEnable(event_tap_data->event_tap,true);

    }

    CGPoint point = CGEventGetLocation(event);
    NSPoint old_point;

    CGPoint target; 
    int tX = point.x; 
    int tY = point.y; 
    float oX = screen_width/2;
    float oY = screen_height/2;
    float dX = tX-oX;
    float dY = tY-oY;

    old_point.x = floor(oX); old_point.y = floor(oY);

    dX*=2, dY*=2;

    tX = round(oX + dX);
    tY = round(oY + dY);


    target = CGPointMake(tX, tY);


    CGWarpMouseCursorPosition(old_point);
    CGEventSetLocation(event,target);


    [pool release];

    return event;
}

最佳答案

当事件点击接收到 kCGEventTapDisabledByTimeoutkCGEventTapDisabledByUserInput 时,您需要重新启用事件点击。


更新:这是您的线路以及它们(失败)如何工作:

CFMachPortRef eventTap; // uninitialized value
CFMachPortRef *eventTapPtr = &eventTap; // pointer to eventTap
struct event_tap_data_struct event_tap_data = {*eventTapPtr,0.2}; // dereferences pointer, copying uninitialized value into struct

eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data); // sets eventTap but has no effect on event_tap_data

关于objective-c - 段错误 11 | CGEventTap 应用程序在任意时间后停止处理鼠标事件。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10365487/

相关文章:

ios - 以编程方式设置 UITabBarController 的 viewControllers 和 selectedIndex 导致未选择 UITabBarItem

iPhone:如何从 url 获取 UIImage?

Python - 增加 mac osx 中的递归限制

ios - "unexpectedly found nil"超出 viewDidLoad

cocoa - 如何使用 Cocoa 实现布局编辑器

objective-c - 为什么viewController的初始化器没有在它的接口(interface)文件中声明?

cocoa - 如何将 NSImage 上传到 Facebook-Graph Api(通过 HTTP POST)

Cocoa CGColorRef 不兼容的指针类型传递 float [4 ]' to parameter of type ' const CGFloat *' (aka ' const double *')

objective-c - 如何在 OS X Finder 中有条件地为文件和文件夹着色?

iphone - 将 UIButton 添加到 MKAnnotationView