在Mojave上获取鼠标坐标 [英] Getting mouse coordinates on Mojave

查看:59
本文介绍了在Mojave上获取鼠标坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常基本的小命令行应用程序,下次单击鼠标时会捕获鼠标坐标.

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    CGFloat displayScale = 1.0f;
    if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)])
    {
        displayScale = [NSScreen mainScreen].backingScaleFactor;
    }

    CGPoint loc = CGEventGetLocation(event);
    CFRelease(event);
    printf("%dx%d\n", (int)roundf(loc.x * displayScale), (int)roundf(loc.y * displayScale) );
    exit(0);
    return event;
}

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

        CFMachPortRef eventTap;
        CGEventMask eventMask;
        CFRunLoopSourceRef runLoopSource;
        eventMask = 1 << kCGEventLeftMouseDown;
        eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
                                    1, eventMask, myCGEventCallback, @"mydata");

        runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                           kCFRunLoopCommonModes);
        CGEventTapEnable(eventTap, true);
        CFRunLoopRun();
    }
    return 0;
}

我正在使用带有以下文件的cmake进行构建:

cmake_minimum_required(VERSION 3.0.0)


project (location)

set(CMAKE_C_FLAGS "-arch x86_64 -mmacosx-version-min=10.12 -std=gnu11 -fobjc-arc -fmodules")

在升级到Mojave之前,一切正常.

仔细一看,可以看出这取决于最新的安全更新集和一些

此应用程序只是抓住屏幕区域的左上角,以馈送到第二个应用程序,该应用程序将屏幕的该区域流式传输到第二个设备.流媒体的代码在Win/Linux/MacOS上很常见,因此请尝试将屏幕坐标集合完全分开

我发现CGEventTap文档已从Mojave开始过时.以root身份运行通常会绕过某些权利,但是在Mojave中,这种情况已得到严格处理.正如您所注意到的,一个奇怪的副作用是,根仍然可以获取水龙头的马赫数.只是无法从中读取任何事件.如果您在没有以root用户身份运行的情况下尝试应用程序,则应该获得预期的弹出窗口以请求权限.

如果没有弹出窗口,或者出于其他目的需要以root用户身份运行,则可以通过SystemPreferences -> Security & Privacy -> Privacy -> Accessibility

将应用程序手动添加到受信任的TCC数据库中.

在Info.plist中设置一些值,以允许该应用使用可访问性API

我相信您的意思是添加权利(这也是一个plist).允许应用程序使用Accessibility API的权利是com.apple.private.tcc.allow权利(值为kTCCServiceAccessibility).正如您可能从名称中猜到的那样,仅Apple签署的二进制文件才允许使用它.

如果禁用系统完整性保护(SIP)并使用选项amfi_get_out_of_my_way=1引导内核,则可以将这些权利添加到自己的应用程序中,但我不建议这样做(当然,您的任何客户都不希望这样做)到).在仅禁用SIP的情况下,您可以手动将一个条目添加到TCC数据库中以授予特权,但是仍然不建议这样做.

可能的选择

您可以使用事件监视器:

NSEventMask mask = (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask);
mouseEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask: mask
                     handler:^(NSEvent *event){
                         // get the current coordinates with this
                         NSPoint coords = [NSEvent mouseLocation];
                         // event cooordinates would be event.absoluteX and event.absoluteY
                         ... do stuff
                     }];

文档中确实提到:

仅在启用辅助功能或信任您的应用程序具有辅助功能访问的情况下,才可以监视与键有关的事件.(请参阅AXIsProcessTrusted).

但是我认为这不适用于鼠标事件.

I have a really basic little command line app that grabs the mouse coordinates the next time the mouse is clicked.

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    CGFloat displayScale = 1.0f;
    if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)])
    {
        displayScale = [NSScreen mainScreen].backingScaleFactor;
    }

    CGPoint loc = CGEventGetLocation(event);
    CFRelease(event);
    printf("%dx%d\n", (int)roundf(loc.x * displayScale), (int)roundf(loc.y * displayScale) );
    exit(0);
    return event;
}

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

        CFMachPortRef eventTap;
        CGEventMask eventMask;
        CFRunLoopSourceRef runLoopSource;
        eventMask = 1 << kCGEventLeftMouseDown;
        eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
                                    1, eventMask, myCGEventCallback, @"mydata");

        runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                           kCFRunLoopCommonModes);
        CGEventTapEnable(eventTap, true);
        CFRunLoopRun();
    }
    return 0;
}

I'm building it with cmake with the following file:

cmake_minimum_required(VERSION 3.0.0)


project (location)

set(CMAKE_C_FLAGS "-arch x86_64 -mmacosx-version-min=10.12 -std=gnu11 -fobjc-arc -fmodules")

This all worked fine until the upgrade to Mojave.

A bit of poking around shows this is down to the latest set of security updates and some hints (except CGEventTapCreate() is not returning null) about settings some values in Info.plist to allow the app to use the accessibility API. But I'm struggling to work out where to put it as I just have a single .m file with the code.

Edit

  • This needs to run as a none root user (company policy)
  • if the only way to get it to ask for permission then it can be extended to be a "GUI" app with a minimal UI

This app is just to grab the upper left hand corner of a region of the screen to feed to a second app that streams that area of screen to a second device. The code for the streamer is common across Win/Linux/MacOS so trying to keep the screen coordinate collection totally separate

解决方案

I've found the CGEventTap documentation is out of date beginning with Mojave. Running as root used to act as a bypass for certain entitlements, but in Mojave this was tightened down. One bizarre side effect, as you noticed, is that root can still acquire the mach port for the tap; its just that no events can be read from it. If you try your application without running as root you should get the expected popup asking for permission.

If you do not get the popup, or need to run as root for other purposes, you can manually add your application to the trusted TCC database via SystemPreferences -> Security & Privacy -> Privacy -> Accessibility

settings some values in Info.plist to allow the app to use the accessibility API

I believe you mean adding entitlements (which are also a plist). The entitlement that allows an application to use the Accessibility API is the com.apple.private.tcc.allow entitlement (with a value of kTCCServiceAccessibility). As you can probably guess from the name it is only allowed on Apple signed binaries.

You can add these entitlements to your own app if you disable System Integrity Protection (SIP) and boot the kernel with the option amfi_get_out_of_my_way=1, but I wouldn't recommend it (and certainly any customers of yours wouldn't want to). With just SIP disabled you could manually add an entry to the TCC database to grant privileges, but still wouldn't recommend it.

Possible Alternative

You can use an event monitor:

NSEventMask mask = (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask);
mouseEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask: mask
                     handler:^(NSEvent *event){
                         // get the current coordinates with this
                         NSPoint coords = [NSEvent mouseLocation];
                         // event cooordinates would be event.absoluteX and event.absoluteY
                         ... do stuff
                     }];

The documentation does mention:

Key-related events may only be monitored if accessibility is enabled or if your application is trusted for accessibility access (see AXIsProcessTrusted).

But I don't think that applies to mouse events.

这篇关于在Mojave上获取鼠标坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆