在Mac上将鼠标限制为一个显示器(可能使用Cocoa)

Bum*_*imp 5 macos mouse cocoa multiple-monitors objective-c

我一直在疯狂地寻找一种方法,该方法可将用户的鼠标限制在Mac上的多显示器设置中的一个显示器上。

我偶然发现了这个问题:可可:将鼠标限制在屏幕上,我保证我没有重复这个问题。

但是,这个问题确实激发了我的想法,即可以使用Cocoa编写一个简单的应用程序以将鼠标限制在一个屏幕上,在后台运行该应用程序,并且仍然可以使用我在AS3中开发的游戏/ Adob​​e AIR / Flash。

该游戏是全屏游戏,并且在同一台显示器上始终具有相同的分辨率。另一台监视器也将始终具有相同的分辨率,但仅仅是信息的非交互式显示。我需要用户能够与游戏进行交互,但不能意外地将鼠标移出游戏屏幕。

问题摘要: 我可以使用Cocoa / Objective C为Mac OS X(Lion)创建一个基本应用程序,该应用程序将鼠标限制为可以在后台运行的一台显示器,并防止用户将鼠标移到具有该功能的显示器之外。一个全屏游戏可以运行吗?


[编辑:]我找到了运行Quartz Event Filter循环的必要基本代码,这是由以下答案提供的:修改NSEvent以发送与按下的键不同的键

我将使用该代码进行测试,并且对它进行了一些修改以检测鼠标事件,如下所示:

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

    NSPoint point = CGEventGetLocation(event);
    NSPoint target = NSMakePoint(100,100);
    if (point.x >= 500){
        CGEventSetLocation(event,target);

    }
    return event;
}

int main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    CFRunLoopSourceRef runLoopSource;

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMouseMoved, 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);
}
Run Code Online (Sandbox Code Playgroud)

但是,这似乎不太正确。当然,它可以正确检测鼠标事件,并且可以正确移动鼠标事件。例如,如果我从屏幕左侧拖动窗口超过500像素,则窗口拖动事件将移至100,100。但是,当鼠标只是在屏幕上移动而不执行其他操作时,鼠标本身不会移动到新位置。IE:您仍然可以将鼠标移动到整个屏幕上,而不只是在左侧的500像素列上。

有任何想法吗?

rob*_*off 3

使用 Quartz Event Tap 过滤鼠标移动和鼠标拖动事件。在点击回调中,用于CGEventSetLocation修改鼠标事件的位置,否则鼠标事件将移出主屏幕。

您可能需要以 root 身份运行该程序,或者在系统偏好设置中启用辅助设备访问。

Quartz 事件服务参考