首页 > 解决方案 > 在 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 之前,这一切都很好。

稍加研究表明,这取决于最新的安全更新集和一些关于设置一些值以允许应用程序使用辅助功能 API 的提示(除了CGEventTapCreate()不返回 null) 。Info.plist但我正在努力找出把它放在哪里,因为我只有一个包含代码的 .m 文件。

编辑

这个应用程序只是抓取屏幕区域的左上角以馈送到第二个应用程序,该应用程序将该屏幕区域流式传输到第二个设备。流媒体的代码在 Win/Linux/MacOS 中是通用的,因此试图将屏幕坐标集合完全分开

标签: macoscocoamacos-mojave

解决方案


我发现CGEventTap从 Mojave 开始的文档已经过时。以 root 身份运行曾经作为绕过某些权利的手段,但在 Mojave 中,这一点被收紧了。正如您所注意到的,一个奇怪的副作用是 root 仍然可以获取用于 tap 的 mach 端口。只是不能从中读取任何事件。如果您在没有以 root 身份运行的情况下尝试您的应用程序,您应该会得到预期的弹出窗口,请求许可。

如果您没有收到弹出窗口,或者出于其他目的需要以 root 身份运行,您可以通过以下方式手动将您的应用程序添加到受信任的 TCC 数据库中SystemPreferences -> Security & Privacy -> Privacy -> Accessibility

在 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)。

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


推荐阅读