我们使用最多的是笛卡尔平面直角坐标系,它以屏幕左下角为原点,向上增加y坐标,向右增加x坐标。
SCWindow的坐标则是以主屏幕左上角为原点的翻转坐标,以下是一个简单的对比图:

在实际场景,尤其是多屏,在两种坐标系之间转换,仍然不是一件容易的事情。
假设有两个显示屏,如下图所示排列:

黑色区域为目标窗口,也是SCWindow的区域(如果你使用SCContentSharingPicker,那么这块区域就是它返回的SCContentFilter.contentRect),我们将要根据这个区域,计算出在平面直角坐标系中的左上角坐标。
- 主屏(2560×1440),左下角原点(0,0),副屏(1920×1080),左下角原点(2560,360)。
- 主屏和副屏的排列方式为,上边缘对齐
- 每个屏幕都会有25px的保留区域,可以认为是系统顶部的状态栏
你看,有很多的干扰因素。有状态栏,有大小不一、排列随时变化的显示器,以及它们不一样的原点。
你只有SCWindow.frame的值,你一开始并不知道SCWindow.frame.origin是翻转的坐标,Apple也不会在任何地方告诉你这一点,这就是苹果软件开发的日常。
好在经过不停地调试,最后我们能自己搞明白,SCWindow使用的是翻转的坐标。
所以上图的答案是(2560,1440-25)。
那么做一些变化呢
将副屏向下移动,使其底部边缘和主屏对齐,原点变为(2560,0):

这次我们知道了,我们要求的结果,和副屏的大小无关,因此省略了无关的细节。
图中两个黑色窗口左上角所在平面直角坐标系的点,如图所示。
可见,这个结果和状态栏的大小也无关。
所以结果就是(目标窗口的x坐标, 主屏高度-目标窗口的y坐标),也就是(x, mainScreen.height-y)吗?
将副屏移动到主屏上方验证一下

在翻转的坐标系上方出现的点,y坐标都变为负数,并且越往上越小。
如图所示,根据我们的公式,(x, mainScreen.height-y),该点在平面直角坐标系中也能正确显示。
这样看起来很简单,但是在你排除掉这些干扰因素之前,这个计算就非常的容易出错了。
以上是我在开发 MagicToy 的屏幕置顶功能的一部分过程。
MagicToy 中的 Always On Top 置顶功能

你可以使用 ⌃ + 左键 单击窗口置顶,也可以使用快捷键选择。你可以使用同样的⌃ + 左键单击已经置顶的窗口取消置顶,或者,右键单击,在弹出菜单中取消置顶。
你还可以将这些快捷键改成你喜欢的选择。
MagicToy 中还有很多类似的功能,如置顶、取色、贴图、右键菜单、状态栏管理、ntfs等等功能,后面将会补充到十几项功能。
我目前正打算将它上架。怎么样,这是你想要的功能吗?