在开发落格输入法的时候,我遇到了这么一件事情,就是作为候选栏的窗口会在屏幕边缘的时候超出屏幕去!所以,在显示窗口的时候我根据坐标做了额外的检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if visiableCandidateCells.isEmpty { if let screenframe = NSScreen.main?.visibleFrame { if screenframe.width < location.x + size.width { location.x -= location.x + size.width - screenframe.width } } } else { if let screenframe = NSScreen.main?.visibleFrame { if screenframe.width < location.x + self.window!.frame.size.width { location.x -= location.x + self.window!.frame.size.width - screenframe.width } } } if location.y < 50 { location.y += 35 + 35 } |
总之,就是说如果坐标算上自己的宽度超过了屏幕的宽度,就把它挪回来。
但是,这样处理不能在多显示器下工作良好,这时由于多显示器坐标导致的:
macOS 的多显示器坐标机制
如上图所示,当用户拥有多个显示器时,显示器的坐标是合并在一起的,同样遵循左负右正的规则,这种情况下,当你的用户在右侧屏幕打字时,一旦光标插入点位置坐标大于屏幕最大坐标(别忘了,右侧屏幕坐标最大值大于它本身宽高),窗口就不会继续往右走了。
这时,要对不同屏幕坐标进行矫正,即不使用屏幕分辨率大小作为判断依据,而是要用屏幕宽高加当前屏幕原点偏移!那么修改后的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
if visiableCandidateCells.isEmpty { if let screenframe = NSScreen.main?.frame { if screenframe.width+screenframe.origin.x < location.x + size.width { location.x -= location.x + size.width - (screenframe.width+screenframe.origin.x) } if location.y < screenframe.origin.y + 50 { location.y += 35 + 35 } } } else { if let screenframe = NSScreen.main?.frame { if screenframe.width+screenframe.origin.x < location.x + self.window!.frame.size.width { location.x -= location.x + self.window!.frame.size.width - (screenframe.width+screenframe.origin.x) } if location.y < screenframe.origin.y + 50 { location.y += 35 + 35 } } } |
这样,在多显示器上,不论用户如何安排显示器排列,候选窗口都不会超出当前屏幕边缘了。
app 窗口全屏问题
这里有一个坑值得谈谈,就是 macOS 上的 work space,多个桌面机制一直是 macOS 优秀的地方,难得的是——你根本没有任何 api 去检查用户在哪个 space 中……
这本来也没什么,可在多屏幕的模式下就出了问题——用户只要在外接屏幕全屏一个app,你就无法获取到正确的屏幕大小了——所以上文中的纠正也就无从谈起。
当你全屏一个app,在此模式下,获取的屏幕大小永远是主屏幕的大小,无论是在哪个屏幕上。
所幸,获取到的输入点坐标还是正确的,所以我还能遍历所有屏幕来查找究竟插入点在哪个屏幕上,然后再根据这个屏幕进行偏移处理。
所以,完整的代码是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var currentScreen = NSScreen.main for scr in NSScreen.screens { if scr.frame.contains(location) { currentScreen = scr break } } if visiableCandidateCells.isEmpty { if let screenframe = currentScreen?.frame { if screenframe.width+screenframe.origin.x < location.x + size.width { location.x -= location.x + size.width - (screenframe.width+screenframe.origin.x) } if location.y < screenframe.origin.y + 50 { location.y += 35 + 35 } } } else { if let screenframe = currentScreen?.frame { if screenframe.width+screenframe.origin.x < location.x + self.window!.frame.size.width { location.x -= location.x + self.window!.frame.size.width - (screenframe.width+screenframe.origin.x) } if location.y < screenframe.origin.y + 50 { location.y += 35 + 35 } } } |
本文由 落格博客 原创撰写:落格博客 » 多显示器下判断窗口位置 macOS
转载请保留出处和原文链接:https://www.logcg.com/archives/2771.html
开发者您好,买了您开发的macOS2输入法,很好用。
但有一小点不足的地方:我macOS(10.13.6)+一个外接显示器。我在外接显示器上全屏某个APP,用shift切换中英文状态时的提示(“En”或“中”的切换)无法表示。没有外接显示器只用macOS时,全屏的APP也有这个现象。仅供参考。
确认有这个问题,我会着手修复。感谢反馈。