如何让 NSWindow 显示在不同的 Space 或者 Screen 中

在写落格输入法 Mac 版的过程当中,我遇到了这么一个问题,系统的候选条 API 年久失修,很多功能 API 存在但根本无效,比如:

这个方法是用来设置候选条风格的,里边除了默认的 IMKCandidatesSendServerKeyEventFirst 这个能生效外,其他的一概无视。

这就尴尬了,现在平明动辄高分4k要么就视网膜,默认的16号候选字体看上去眼睛还不得瞎了。

所以,最后我还是得自己来实现这个候选条,怎么布局以后再说,不过这里有一个很有意思的点可以讲讲,那就是怎么让这个 NSWindow  能跟着用户的输入点走,而不是被“困在”第一个屏幕里。

首先,我是这样设计的

用一个 NSWindow  加适当的改造,然后作为候选栏,调用它的 makeKeyAndOrderFront 来显示,然后用 close 来关闭,然后我就遇到了第一个问题:调用 close 后,这个窗口被释放了!导致程序执行强行遇到空指针,尽管在 Swift 中我是这样声明的  var candidatesWindow:CandidateController 。

所以,我开始想到吸取 OC 里的老一辈宝贵经验,用  self.alphaValue 来搞定这件事情。

透明度

毕竟,透明了就等于隐藏了,也不能交互,在我重写了一系列方法后,看起来工作良好。不过,很快就有用户报告问题,说候选栏有时候会丢失,就是说能打字但是没有候选栏……我一开始以为是插入光标的坐标获取错误……最终在我意外切换 Space 后重现了这一问题,原来候选栏并没有跑偏,只是它显示在了另一个屏幕空间里。

所以我开始寻找怎么把 NSWindow  移动到目标屏幕的办法——其实后很多,但遗憾的是还真的是没有移动 NSWindow  到目标 Space 的办法——这就尴尬了。

于是在3个小时之后,我放弃了这条路,回到了原点。

NSWindowController

既然回到原点,那么我一开始的设计理念其实还是比较正确的,那么矛盾就在于如何让这个窗口不自动释放。遗憾的是网上找了一圈,大家竟然都是在问如何能让窗口正确释放——好吧,我看它就自己释放的挺积极的……………………

总之,这个时候我想到了这个 Controller,毕竟它不会自己把自己给释放了——那么问题来了,如果我 close 了 NSWindowController  ,它会被释放吗?

——幸好,也应该是显然,不会。所以,我就改为了使用 NSWindowController ,然后在初始化的时候来初始化这个窗口。那么当我需要显示候选栏,我就可以这么做:

当我需要关闭的时候,就这么做:

这样,整个的窗口管理就由 NSWindowController 自动安排了,然后重点来了:

由于每次窗口不再是单纯的移动位置和修改透明度,窗口的出现和消失是真正的添加和移除,这就天生支持了在任意屏幕位置显示,这下,候选栏可以支持多屏幕、多 Space 了。

anyShare分享到:

“如何让 NSWindow 显示在不同的 Space 或者 Screen 中”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注