Ограничение мыши одним дисплеем на Mac (возможно с использованием какао) - PullRequest
5 голосов
/ 18 ноября 2011

Я лихорадочно искал метод, с помощью которого можно ограничить мышь пользователя одним дисплеем в настройке мультидисплея на Mac.

Я наткнулся на этот вопрос: Какао: ограничение мыши до экрана , я обещаю, я не дублировал этот вопрос.

Однако этот вопрос вызвал у меня мысль, что можно написать простое приложение, использующее Cocoa, чтобы ограничить мышь одним экраном, запустить это приложение в фоновом режиме и по-прежнему использовать мою игру, которая была разработано в AS3 / Adobe AIR / Flash.

Игра представляет собой полноэкранную игру и всегда будет иметь одинаковое разрешение на одном мониторе. Другой монитор также всегда будет иметь такое же разрешение, но это будет просто неинтерактивное отображение информации. Мне нужно, чтобы пользователь мог взаимодействовать с игрой, а не случайно убирать мышь с игрового экрана.

Сводка вопроса: Могу ли я создать базовое приложение для Mac OS X (Lion), использующее Cocoa / Objective C, которое будет ограничивать мышь одним монитором, который может быть запущен НА ФОНЕ, и не позволит пользователям перемещать мышь за пределы монитора, который будет иметь полную на нем запущена экранная игра?


[EDIT:] Я нашел базовый код, необходимый для запуска цикла для 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);
}

Однако, похоже, это не совсем правильно. Он, безусловно, правильно определяет события мыши и также правильно перемещает события. Например, если я перетаскиваю окно за 500 пикселей с левой стороны экрана, событие перетаскивания окна перемещается на 100,100. Однако сама мышь не перемещается в новое место, когда ее просто перемещают по экрану, не выполняя никаких других действий. IE: вы все еще можете перемещать мышь по всему экрану, а не только в левом столбце 500 пикселей.

Есть идеи?

1 Ответ

3 голосов
/ 18 ноября 2011

Используйте Quartz Event Tap, чтобы отфильтровать события перемещения мыши и перетаскивания мыши.В обратном вызове касания используйте CGEventSetLocation, чтобы изменить местоположение событий мыши, которые в противном случае переместились бы с главного экрана.

Возможно, вам потребуется запустить программу от имени пользователя root или включить вспомогательный доступ к устройству в Системных настройках..

Справочник по службам Quartz Event

...