macos - 在 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 文件。
编辑
- 这需要以非 root 用户身份运行(公司政策)
- 如果是获得许可的唯一方法,那么它可以扩展为具有最小 UI 的“GUI”应用程序
这个应用程序只是抓取屏幕区域的左上角以馈送到第二个应用程序,该应用程序将该屏幕区域流式传输到第二个设备。流媒体的代码在 Win/Linux/MacOS 中是通用的,因此试图将屏幕坐标集合完全分开
解决方案
我发现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)。
但我认为这不适用于鼠标事件。
推荐阅读
- android - 当片段数量超过 50 个但每个片段具有相同的布局和方法时,处理 ViewPager 和片段的正确方法是什么?
- spring-boot - localhost:8080\sendMesssage 上的 Whitelabel 错误页面?
- python - Django / Factoryboy - 无法删除测试中的实例
- sql - 设置新变量等于表达式时列名无效
- docker - 清理 Docker Swarm 中未引用的配置和机密
- css - 使用 Jpeg 用纯 CSS 遮罩另一个图像?
- java - 我无法让应用程序构建 sqlite 数据库
- python-3.x - 如何添加到文件顶部?
- tableau-api - Tableau Server 站点或用户中的任何列是否可自定义?
- android - Android/Kotlin:如何创建一个使用 DBLocal 类的类?错误消息:类型不匹配需要上下文