在寫落格輸入法 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 來顯示,然後用 關 來關閉,然後我就遇到了第一個問題:調用 關 後,這個窗口被釋放了!導致程序執行強行遇到空指針,儘管在 Swift 中我是這樣聲明的 是 candidatesWindow:CandidateController 。
所以,我開始想到吸取 OC 裡的老一輩寶貴經驗,用 自.ALPHAVALUE 來搞定這件事情。
透明度
畢竟,透明了就等於隱藏了,也不能交互,在我重寫了一系列方法後,看起來工作良好。不過,很快就有用戶報告問題,說候選欄有時候會丟失,就是說能打字但是沒有候選欄……我一開始以為是插入光標的坐標獲取錯誤……最終在我意外切換 Space 後重現了這一問題,原來候選欄並沒有跑偏,只是它顯示在了另一個屏幕空間裡。
所以我開始尋找怎麼把 NSWindow 移動到目標屏幕的辦法——其實後很多,但遺憾的是還真的是沒有移動 NSWindow 到目標 Space 的辦法——這就尷尬了。
於是在3個小時之後,我放棄了這條路,回到了原點。
NSWindowController
既然回到原點,那麼我一開始的設計理念其實還是比較正確的,那麼矛盾就在於如何讓這個窗口不自動釋放。遺憾的是網上找了一圈,大家竟然都是在問如何能讓窗口正確釋放——好吧,我看它就自己釋放的挺積極的……………………
總之,這個時候我想到了這個 Controller,畢竟它不會自己把自己給釋放了——那麼問題來了,如果我 關 了 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
註釋