Related sample project: https://github.com/vChewing/vChewing-macOS/tree/3.4.9
It seems that individual bug reports doesn't work at all. Besides, the entire InputMethodKit needs a renovation.
This thread will be sent to Apple by certain special approaches after gathering enough usable information.
Let's talk about what InputMethodKits needs to improve. Here's my conclusion. If Apple think there's already an API, then it might be either mulfunctioning or not exposed to Swift.
-
An official Swift-friendly wrapper with neither "!" nor "?" in the parameters of all provided APIs.
-
Provide effective official exposed Swift access to:
- { get set } WindowLevel of the IMKCandidates, making sure that it won't get covered by NSMenu and Spotlight by default.
- { get set } Default candidate fonts as NSFont
- { get set } Highlight background color of the IMKCandidate panel
- { get set } Window background color tint of the IMKCandidate panel, allowing developers to enable or disable aero-glass transparency.
- { get set } Candidate keys definable in both ways: charCodes and keyCodes.
- { get set } Get the currently-highlighted TOTAL INDEX of the chosen candidate in the current candidate window.
- { get } Add IMKTextInput.isWritingContextVertical.
- { get } Add currentMarkedRangeOrigin (NSPoint), currentMarkedRangeTopLeft (NSPoint), currentMarkedRangeTopRight (NSPoint), currentCursorOrigin (NSPoint), currentCursorTopPoint (NSPoint).
-
IMKInputController.Candidates() can send (Candidate, Reading, Annotation) triplet to the IMKCandidates. Also, IMKInputController.candidateSelected() and IMKInputController.candidateSelectionChanged() retrieves both Candidate and its total index number in the candidate window.
-
Add Home / End key support in the IMKCandidate window.
-
Provide a clear and unified Swift API for sending key NSEvents to IMKCandidates, making sure that these sent events are handled there. At least,
- (BOOL)handleKeyboardEvent:(NSEvent *)event API_AVAILABLE(macosx(10.14));
needs to be officially exposed to developers. -
Add official NSEvent support of detecting whether Shift key has been pressed as a single function key. This is for helping IME developers to provide their own in-method input mode switch. This feature is crucial for users who already got accustomed to how Windows input methods behave. Reasons:
- Ergonomics: "Ctrl" / "CapsLock" / "Fn" key are less friendly than "Shift" key to one's pinkle finger.
- macOS built-in CapsLock IME toggle can have 1-second latency on certain user's computers with totally unknown reasons.
- Most Chinese IME users are from Windows, inheriting their preferences which are uncompromisable at all, period.
- IME-Developer-implemented Shift-key alphanumerical mode toggle can provide a fast way of inputting ASCII alphanumerals without moving the pinkle finger away from the Shift key.
-
Provide a USABLE way of showing a description text at the bottom of the IMKCandidate window. This feature can be used for telling users what this candidate window is prepared for.
-
Official TouchBar IMKCandidates API for 3rd-party input method developers.
-
IMKCandidate window instances need to be separated for each InputMethodController. Reason: The IMKController session of an app sometimes deactivates after the one of the another client app gets activated, leading to the mess of handling input states. Imagine that you switched to another app and immediately want to call the symbol menu (shown through IMKCandidates), but the symbol menu window gets disappeared due to deactivateServer() triggered by another client app.
-
Please state clearly in the documentation of certain APIs (like
(de)activateServer()
andsetValue()
) if they are expected to be mission-critical (e.g. expected to finish their processings as fast as possible). Otherwise, this can cause responsiveness issues of an input method if it is using Swift and is not using Grand Central Dispatch. -
An official workable solution (with precise sample project) demonstrating how to implement the IME settings pane of the System Preferences / Settings window:
-
The documentation of InputMethodKit needs update regarding how to make sure annotations are shown in IMKCandidates. A Swift-only example is warmly welcomed.
-
Different IMKInputController session instances might interfere each other: When activating a new instance of such in Safari new tab, the previous instance may deactivate later than the current one. However, this deactivation process may close the IMKCandidate window called by the current instance, confusing the user who are using the current input session because he / she can't tell which input state it currently is: It's actually a candidate state, but the candidate window is closed by the previous deactivated input session.
-
The menu item "Edit Text Substitutions…" in the input source menu has been mistranslated as "Edit User Dictionary" which is extremely misleading to 3rd-party input method users.
-
macOS 14 Sonoma needs to provide an official instructive documentation regarding how the icons of 3rd-party input methods should be designed to make sure they are stylisticly unified with system built-in input methods.
-
The documentation of InputMethodKit needs to be updated to ask developers to change their InputMethodConnectionName to
$(PRODUCT_BUNDLE_IDENTIFIER)_Connection
in order not to let their input methods occasionally greyed out in the input source menu.
According to WWDC 2006 presentation "Input Method Kit Overview" held by Lee Collins, the InputMethodConnectionName in the info.plist of an input method should "Do not include spaces in the name or periods." However, in recent macOS, it can be occasionally observed that the right answer is $(PRODUCT_BUNDLE_IDENTIFIER)_Connection
for sandboxed 3rd-party input methods. Even if you have set your InputMethodConnectionName to something else, in rare cases (mostly after your laptop gets woke up in macOS 13.4 Ventura) the system might dismiss your specified connection name and use $(PRODUCT_BUNDLE_IDENTIFIER)_Connection
to make a connection instead, hence refusal by (possibly) Sandbox. At least, in such occasion, you can only see the affected input methods gray out in the input source menu before your mac reboots.
Therefore, it is necessary to update the following page:
https://developer.apple.com/documentation/appkit/nstextinputcontext/1529156-keyboardinputsources
... to add the recommended value for InputMethodConnectionName
as $(PRODUCT_BUNDLE_IDENTIFIER)_Connection
instead of the one suggested in WWDC2006.
Additional notes: Since macOS 10.14 till now, in order to use IMKCandidates, these following APIs have to be exposed through bridging-header:
@interface IMKCandidates(PROJECT_TARGET_NAME) {}
- (unsigned long long)windowLevel API_AVAILABLE(macosx(10.14));
- (void)setWindowLevel:(unsigned long long)level API_AVAILABLE(macosx(10.14));
- (BOOL)handleKeyboardEvent:(NSEvent *)event API_AVAILABLE(macosx(10.14));
- (void)setFontSize:(double)fontSize API_AVAILABLE(macosx(10.14));
@end
Finally, please allow input methods sellable on Mac App Store. A macOS input method app can be installed in the ~/Library/Input Methods/ and is okay to be Sandboxed (e.g. vChewing since v2.3.0). Therefore, there should be no privacy concerns anymore.
关联专案: https://github.com/vChewing/vChewing-macOS/tree/3.4.9
似乎单独的 BugReport 并不能起多少及时的作用,且整个 InputMethodKit 可能需要大翻新。
该讨论串会在筹集到足够的资讯的时候借由特殊渠道递交给 Apple。
先聊一下 InputMethodKit 有哪些需要改善的地方吧。下面是我的结论。如果 Apple 认为已经有对应 API 的话,要么这些 API 要么罢工了、要么没曝露给 Swift。
var windowLevel: Double { get set }
,确保 IMK 选字窗不会被 NSMenu 和 Spotlight 遮住。这个毛病始于 macOS 10.14,令人怀疑 IMK 的单元测试的设计是否足够健全。var defaultCandidateFonts: NSFont { get set }
。这是选字窗字型。目前的 API 用了没有任何效果。实际需求就是用CTFontCreateUIFontForLanguage(.system, size, locale as CFString)
指定使用哪个语种的系统字型来显示候选字。var highlightBackgroundColor: NSColor { get set }
用来指定候选字高亮背景色。顺便一提:macOS 内建的注音输入法的 IMK 选字窗的候选字高亮背景色是会跟随客体应用的 ThemeColor 自动调整的,要是给第三方输入法用的 IMKCandidates 也能这样就好了。var windowBackgroundColor: NSColor
,允许第三方输入法开发者启用或者停用 Windows Aero 玻璃背景特效。var candidateKeysOfChars: [Character] { get set }
和var candidateKeys: [KeyCode] { get set }
允许第三方输入法开发者既可以用 String 字符、又可以用 KeyCode 定义选字键。// 目前的 IMKCandidates 任何与选字键定义有关的 API 都是失效的。currentMarkedRangeOrigin (NSPoint)
、currentMarkedRangeTopLeft (NSPoint)
、currentMarkedRangeTopRight (NSPoint)
、currentCursorOrigin (NSPoint)
、currentCursorTopPoint (NSPoint)
。(Candidate, Reading, Annotation)
这个 triplet 类型、给 IMKCandidates 处理,以简化 Annotation 的显示调度流程。同时,IMKInputController.candidateSelected()
以及IMKInputController.candidateSelectionChanged()
不只得拿到当前的候选字词、还得拿到其在候选字词阵列池当中的顺序编号(以 0 起算)。IMKInputController.handle(event:)
手动传递给 IMKCandidates。至少,- (BOOL)handleKeyboardEvent:(NSEvent *)event API_AVAILABLE(macosx(10.14));
这个 macOS 10.14 开始才有的 API 得曝露给第三方输入法开发者。(de)activateServer()
和setValue()
)。不然的话,如果是用 Swift 写输入法、且没有充分利用 Grand Central Dispatch 的话,某些 API 实作的运作效率没有足够的优化,会让输入法变得略显迟钝。整个 InputMethodKit 的说明文件都得需要更新,以指引使用者如何在 IMKCandidates 当中显示 annotation。最好有一个纯 Swift 的 Xcode 范例专案。
不同的 IMKInputController 会话副本会影响彼此:当你 activate 了一个新的副本的时候(比如说 Safari 的 new tab),之前的旧副本往往会在此之后才会 deactivate。与此有关的选字窗显示的问题,我已经在上文吐槽过了。但目前这一条是想建议 Apple 在 InputMethodKit 的说明文件当中仔细说明该特性、来指导第三方输入法开发者们该怎样正确处理。
输入法选单的「Edit Text Substitutions…」被讹译成「编辑使用者辞典…」,非常误导第三方输入法的使用者。身为威注音输入法的开发者,我到现在已经好几次被新手问到「点了『编辑使用者辞典…』无法修改威注音输入法的使用者辞典」,我只能把威注音输入法的「编辑自订语汇」改名为「编辑威注音自订语汇」。
macOS 14 Sonoma 需要一套官方的「第三方输入法选单图示设计指南」,仔细阐明(macOS 13 开始的)「宽版输入法选单图示」与(macOS 14 开始才有的)「上下文输入法指示器」该怎样设计与实装、才能使其视觉风格表现与 macOS 内建输入法彼此统一。
目前的 InputMethodKit 的说明文件还需要更新,劝诫第三方输入法开发者统一将输入法的 info.plist 当中的
InputMethodConnectionName
以及沙盒 Entitlements 当中的com.apple.security.temporary-exception.mach-register.global-name
都改成$(PRODUCT_BUNDLE_IDENTIFIER)_Connection
。不然的话,在某些情况下,macOS 会无视开发者指定的 connection name,而是直接以$(PRODUCT_BUNDLE_IDENTIFIER)_Connection
试图启动 IMKServer 连线,然后输入法就会在输入法选单当中一直保持灰色不可选的状态、直至使用者再次重新开机。这一点与 WWDC 2006 的北京输入法讲座的内容有出入(那个讲座不鼓励在 connection name 当中使用小数点)。补记:从 macOS 10.14 Mojave 开始,为了让 IMKCandidates 至少「能用」,下述四个 API 必须借由 bridging-header 强制曝露给 Swift:
最后,请允许第三方输入法开发者将 macOS 平台的输入法在 Mac App Store 贩售。第三方输入法可以安装在「~/Library/Input Methods」使用者目录内,可以沙盒化(比如《威注音输入法》),理应不会再有任何的资安疑虑。
WWDC 2023 Apple Lab Office Hour
该怎样才能在不强制曝露
(unsigned long long)windowLevel
和(void)setWindowLevel:(unsigned long long)level
这两个 API 的情况下、在 macOS 10.14 开始的系统内将 IMKCandidates 选字窗 显示在任何 NSMenu 以及 Spotlight 的上方(不被遮住)?该怎样才能(在 macOS 10.14 开始的系统内)让按键输入(特别是选字键按键输入)被 IMKCandidates 正确受理应对、而无须强制曝露系统 API
(BOOL)handleKeyboardEvent:(NSEvent *)event
?该怎样才能(在 macOS 10.14 开始的系统内)自订 IMKCandidates 的候选字词字号大小、而无须强制曝露系统 API
(void)setFontSize:(double)fontSize
?该怎样在 macOS 10.15 开始的系统内让输入法的 Preferences 设定面板正确地镶嵌显示在系统偏好设定当中?该功能是我按照 Mizuno Hiroki(在他加入 Apple 之前写)的 InputMethodKit 教材当中的指引来实作的,对 macOS 10.13 和 10.14 有效。我现在拿这个问题请教 Mizuno Hiroki 本人,但他却受限于 Apple 公司内部的资安保密限制、什么都不能讲。