在 macOS 上,安装输入法一直是一个噩梦,要打开系统输入法目录,要把输入法拖拽进这个目录,过程中还要输入密码,全手动也就罢了,还得重启后系统才能识别,真的是让人头疼的不行。
后来大家逐渐意识到这个问题,落格输入法也提供了 macOS 标准的 pkg 安装包。
说是这么说,但实际上似乎还是有办法让系统自动加载输入法的,比如搜狗就做到了免重启,安装后不光不需要重启系统就能识别,甚至安装包还能帮你自动选好搜狗输入法!
他们究竟是怎么做到的不得而知,我也对此进行了我自己的研究。
配置文件
总之,一切都是从配置文件开始的,首先我找到了系统要读取的配置文件,这个文件决定了用户当前激活哪些输入法,选中的是哪个输入法:
1 |
~/Library/Preferences/com.apple.HIToolbox.plist |
在这个 plist 中,有 AppleEnabledInputSources 字段,这里边包含了当前都启用了哪些输入法,比如搜狗输入法、落格输入法、系统拼音等等; AppleInputSourceHistory 字段则包含了用户的切换历史,似乎和自动切换有关; AppleSelectedInputSources 字段则表明了当前用户选中的输入法,比如你当前用落格输入法在打字,那么这里就是落格输入法,如果你切换到了英文键盘,那么这里就会变成英文键盘。
理论上,我们编辑这个文件,就可以改变系统的配置,但显然,这个配置文件不是实时读取的,我们编辑该文件后,用终端命令重启偏好管理系统和 Finder: killall cfprefsd && killall Finder
运气好的话,就已经 ok 了。
——-事实上,一般你不会运气好。
显然,想要保险的话,还是重启一下才行。总之,这已经是一个进步了,毕竟重启完不需要用户手动添加输入法了对吧?
系统级别 API
那么,能不能有其他更优雅的方案呢?最终我在 Carbon 框架找到了答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* *=============================================================================== * Install/register an input source *=============================================================================== */ /* * TISRegisterInputSource() * * Summary: * Registers the new input source(s) in a file or bundle so that a * TISInputSourceRef can immediately be obtained for each of the new * input source(s). * * Discussion: * This allows an installer for an input method bundle or a keyboard * layout file or bundle to notify the system that these new input * sources should be registered. The system can then locate the * specified file or bundle and perform any necessary cache rebuilds * so that the installer can immediately call * TISCreateInputSourceList with appropriate properties (e.g. * BundleID or InputSourceID) in order to get TISInputSourceRefs for * one or more of the newly registered input sources. * * This can only be used to register the following: * * - Keyboard layout files or bundles in "/Library/Keyboard * Layouts/" or "~/Library/Keyboard Layouts/" (available to all * users or current user, respectively). Such keyboard layouts, once * enabled, are selectable. * * - Input method bundles in the new "/Library/Input Methods/" or * "~/Library/Input Methods/" directories (available to all users or * current user, respectively). * * Note: Input method bundles can include private non-selectable * keyboard layouts for use with * TISSetInputMethodKeyboardLayoutOverride. These are registered * automatically when the input method is registered, and do not * need to be separately registered. * * Security: Any code that calls TISRegisterInputSource is part of * an application or service that has already been validated in some * way (e.g. by the user). * * Parameters: * * location: * CFURLRef for the location of the input source(s), a file or * bundle. * * Result: * Error code: paramErr if location is invalid or the input * source(s) in the specified location cannot be registered; * otherwise noErr. * * Availability: * Mac OS X: in version 10.5 and later in Carbon.framework * CarbonLib: not available * Non-Carbon CFM: not available */ extern OSStatus TISRegisterInputSource(CFURLRef location) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; |
对于 Swift 来说,也能无痛调用,我们在安装好输入法后,只需要将输入法 app 文件地址传给这个函数,它就可以在系统中注册输入法,这下无需重启就能让系统识别到输入法了:
1 2 3 |
let url = URL(fileURLWithPath: "/Library/Input Methods/LogInputMac2.app") let err = TISRegisterInputSource(url as CFURL) guard err != paramErr else {return} |
记得 import Carbon
接下来,我还想让系统自动把我的输入法添加的切换列表里(即激活输入法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * TISEnableInputSource() * * Summary: * Enables the specified input source. * * Discussion: * TISEnableInputSource is mainly intended for input methods, or for * applications that supply their own input sources (e.g. * applications that provide keyboard layouts or palette input * methods, and keyboard input methods that provide their own * keyboard layouts and/or input modes). It makes the specified * input source available in UI for selection. * * For TISEnableInputSource to succeed, the input source must be * capable of being enabled (kTISPropertyInputSourceIsEnableCapable * must be true). Furthermore, if the input source is an input mode, * its parent must already be enabled for the mode to become enabled. * * Result: * Returns an error code: paramErr if the input source cannot be * enabled, else noErr. * * Availability: * Mac OS X: in version 10.5 and later in Carbon.framework * CarbonLib: not available * Non-Carbon CFM: not available */ extern OSStatus TISEnableInputSource(TISInputSourceRef inputSource) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; |
这个函数调用起来就没那么容易了,主要的难点就是这个 TISInputSource 没办法直接创建,所以要用到另一个函数来搜索,我们已经在系统中注册了落格输入法,接下来就是在所有的可用输入法中找到落格输入法这个输入源,如果直接穷举所有可用输入源,会很慢(API 原话),我们需要加入条件搜索:
1 2 3 4 5 6 |
let conditions = NSMutableDictionary() conditions.setValue(“落格输入法id”, forKey: kTISPropertyBundleID as String) guard let array = TISCreateInputSourceList (conditions, true)?.takeRetainedValue() as? [TISInputSource] else { return } |
如无意外,我们就可以拿到落格输入法的输入源了,这里有两个,一个是输入法,一个是用来真正给用户能输入的输入模式(在用户角度来看这两者是同一个,因为落格输入法就只有一个输入模式——中英文模式是这个唯一模式的两个不同状态)。
接下来就是添加了:
1 2 |
TISEnableInputSource(source) TISSelectInputSource(source) |
这下,用户就可以在安装完成后立即在右上角点击切换到落格输入法——运气好的话,连切换都不需要。
讨论
这个方法看上去很美好,似乎从 macOS 10.5 开始就能用,但实际测试来看只有最新的 macOS Mojave 10.14 是有效的,我在 10.13 上测试无效,不论是改配置还是调用系统 API,全都无动于衷,我倾向于是我这个特定系统版本的 bug,因为 API 调用后右上角的图标已经时落个输入法的图标,但选择列表中并没有落格输入法,甚至注册都失败了。
总之,对于 10.14 的新用户来说,安装落格输入法的体验变得极佳。
本文由 落格博客 原创撰写:落格博客 » 落格输入法 macOS 2 是如何实现免重启激活输入法的
转载请保留出处和原文链接:https://www.logcg.com/archives/3263.html