在写落格输入法 Mac 版的过程当中,我遇到了这么一个问题,系统的候选条 API 年久失修,很多功能 API 存在但根本无效,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/*! @method @abstract Sets the "style" attributes for the candidates window. The keys for the attributes dictionary and the values are: NSFontAttributeName (value = NSFont) Setting the font attribute sets the font that is used to draw Candidates. It does not effect the selection keys which are always drawn in the same font. Note that to set the font size you should use this key/value pair. IMKCandidatesOpacityAttributeName (value = NSNumber with a float value between 0 and 1). Sets the opacity level to transparent (0.0) to completely opaque (1.0). The default opacity is 1.0. This constant is declared above. NSForegroundColorAttributeName (value = NSColor) Sets the text color used for the candidate text. By default it is black. NSBackgroundColorDocumentAttribute (value = NSColor). Set the background color that is drawn behind the candidate text. IMKCandidatesSendServerKeyEventFirst (value = NSNumber). NO (default) gives the candidate window first chance at key events. YES causes events to first be routed to the current IMKInputController. In that case, if the event is not handled, it will then be sent to the candidate window. */ open func setAttributes(_ attributes: [AnyHashable : Any]!) |
这个方法是用来设置候选条风格的,里边除了默认的 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 ,然后在初始化的时候来初始化这个窗口。那么当我需要显示候选栏,我就可以这么做:
1 2 |
self.window!.setFrameOrigin(location) self.showWindow(self) |
当我需要关闭的时候,就这么做:
1 |
self.close() |
这样,整个的窗口管理就由 NSWindowController 自动安排了,然后重点来了:
由于每次窗口不再是单纯的移动位置和修改透明度,窗口的出现和消失是真正的添加和移除,这就天生支持了在任意屏幕位置显示,这下,候选栏可以支持多屏幕、多 Space 了。
本文由 落格博客 原创撰写:落格博客 » 如何让 NSWindow 显示在不同的 Space 或者 Screen 中
转载请保留出处和原文链接:https://www.logcg.com/archives/2769.html
Comments