多显示器下判断窗口位置 macOS

2017-07-06 10:38:18来源:https://www.logcg.com/archives/2771.html作者:落格博客人点击

最近更新:5th 七月, 2017


在开发落格输入法的时候,我遇到了这么一件事情,就是作为候选栏的窗口会在屏幕边缘的时候超出屏幕去!所以,在显示窗口的时候我根据坐标做了额外的检查:


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 的多显示器坐标机制



macOS 上的多显示器坐标机制


如上图所示,当用户拥有多个显示器时,显示器的坐标是合并在一起的,同样遵循左负右正的规则,这种情况下,当你的用户在右侧屏幕打字时,一旦光标插入点位置坐标大于屏幕最大坐标(别忘了,右侧屏幕坐标最大值大于它本身宽高),窗口就不会继续往右走了。


这时,要对不同屏幕坐标进行矫正,即不使用屏幕分辨率大小作为判断依据,而是要用屏幕宽高加当前屏幕原点偏移!那么修改后的代码如下:


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,在此模式下,获取的屏幕大小永远是主屏幕的大小,无论是在哪个屏幕上。


所幸,获取到的输入点坐标还是正确的,所以我还能遍历所有屏幕来查找究竟插入点在哪个屏幕上,然后再根据这个屏幕进行偏移处理。


所以,完整的代码是这样的:


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
}
}
}

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台