当 macOS Catalina 中存在多个 NSScreen 时,确定鼠标光标在 NSScreen 上的 X 位置

Determining Mouse Cursor X Position on NSScreen When Multiple NSScreens are Present in macOS Catalina

我的 Mac 设置是这样的:5K 显示器排列在 Mac 的内置显示器之上。

如果我的鼠标光标在 5K 显示器上,我尝试这样获取鼠标位置:

CGEventRef ourEvent = CGEventCreate(NULL);
NSPoint point = CGEventGetLocation(ourEvent);
CFRelease(ourEvent);

我得到 point.x 的意外 return 值。例如,如果光标在这个位置:

NSLog(@"MOUSE POSITION X: %.0f px", point.x);

然后我回来MOUSE POSITION X: 1950 px。然而,像 Xscope 这样的应用程序将此 x 位置报告为 3900 px

这些值似乎都不正确,因为屏幕被报告为 2560 宽:

NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation];
NSLog(@"SCREEN WIDTH: %f", currentScreen.frame.size.width);

注意:currentScreenForMouseLocation 来自 NSScreen-PointConversion.

如果我将 13" 内置显示器的排列从中心移开,但仍在 5K 显示器下方,point.x 值就更不准确了。我可以看到两者之间存在一些关系数学屏幕上的差异 size/resolution,但我很难弄清楚到底发生了什么,以及如何最终将其转化为代码,以便我可以获得鼠标的真实 point.x 值光标位置。

我要解决的问题是我需要以编程方式显示 NSStatusItem 的菜单,并且我需要确定菜单是否太宽而无法显示在 NSStatusItem 的右侧。我的代码通常工作正常,除了在这种垂直排列显示的特定情况下。在这种情况下,可能会发生这样的事情:

内置显示器设置为主显示器。你可以在系统偏好设置的显示窗格的屏幕截图中看出,因为符号菜单栏就在上面。

也就是说它的左上角是Cocoa坐标系的原点。因此,外部显示器上的任何点都将与其相关,因此显示器的相对位置会影响报告的光标位置。

我建议,首先,您使用 Cocoa,而不是 Core Graphics,来获取当前鼠标位置。然后,您需要将其调整为相对于其所在屏幕的原点(如果您对此感兴趣):

NSPoint pt = [NSEvent mouseLocation];
NSScreen* currentScreen = [NSScreen currentScreenForMouseLocation];
pt.x -= currentScreen.frame.origin.x;
pt.y -= currentScreen.frame.origin.y;

也就是说,听起来您只是要将点与屏幕的右边缘进行比较,这也会相对于主显示器的原点进行报告。那么,为什么不直接将原始点与屏幕框架的 MaxX()

进行比较呢?
NSPoint pt = [NSEvent mouseLocation];
NSScreen* currentScreen = [NSScreen currentScreenForMouseLocation];
if (pt.x + menuWidth >= NSMaxX(currentScreen.frame))
    ...;