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

时间:2011-11-18 19:42:34

标签: objective-c macos cocoa mouse multiple-monitors

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

我偶然发现了这个问题:Cocoa: Limit mouse to screen,我保证我没有重复这个问题。

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

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

问题摘要: 我是否可以使用Cocoa / Objective C为Mac OS X(Lion)创建一个基本应用程序,它将鼠标限制为一个可以在后台运行的监视器,并防止用户将鼠标移动到监视器之外屏幕游戏在它上面运行?


[编辑:] 我找到了为Quartz事件过滤器运行循环所需的基本代码,这个答案很有用:Modify NSEvent to send a different key than the one that was pressed

我将使用该代码进行测试,我已经修改了一下以检测鼠标事件,如下所示:

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);
}
然而,这似乎不太正常。它肯定正确地检测鼠标事件,并且它也正确地移动事件。例如,如果我将窗口从屏幕左侧拖过500像素,则窗口拖动事件将移动到100,100。但是,当鼠标只是在屏幕上移动时,鼠标本身不会移动到新位置,不会执行任何其他操作。 IE:您仍然可以在屏幕上移动鼠标,而不是仅在左侧500像素列上移动鼠标。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

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

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

Quartz Event Services Reference