🌓入力モード
一部の入力メソッドは複数のモードを持つ。例えば、macOS標準の日本語入力がひらがな入力モードとカタカナ入力モードを持つ。
EmojiIMを拡張し、絵文字入力モードとアルファベット入力モードの2つのモードを実装した。
📚関連資料
入力モードに関する資料は複数の箇所に分散している。 一箇所にまとめておいてほしい。
📝ソースコード
https://github.com/mzp/EmojiIM/pull/14
✨ 入力モードの定義
入力モードを定義するために、Info.plistに ComponentInputModeDict
キーを追加する。 ComponentInputModeDict
の値は辞書型であり、以下の2つのキーを持つ。
tsVisibleInputModeOrderedArrayKey
: 入力モードを定義するkTSVisibleInputModeOrderedArrayKey
: 表示順を定義する。
tsVisibleInputModeOrderedArrayKey
の辞書型であり、入力モードを識別するIDをキーとして持つため、おおまかに以下のような構造をとる。
<key>ComponentInputModeDict</key> <dict> <key>tsInputModeListKey</key> <dict> <Key>入力モードID 1</key> <Dict><!-- 入力モードの定義 --></dict> <Key>入力モードID 2</key> <dict><!-- 入力モードの定義 --></dict> </dict> <key>tsVisibleInputModeOrderedArrayKey</key> <array> <String>入力モードID 1</string> <String>入力モードID 2</string> </array> </dict>
入力モードのIDは既存の入力モードと同じ機能を提供する場合は同じキーを使い、独自の機能を提供する場合は独自のIDを使う。 既存の入力モードのIDはTextServices.hで定義されており、com.apple.inputmethod.Roman
や com.apple.inputmethod.Japanese.Hiragana
などがある。
入力モードの定義も辞書型になっており、以下のキーを持つ。
キー名 | 必須・任意 | 意味 |
---|---|---|
TISInputSourceID | 任意 | 入力メソッドのbundle identifierからはじまる識別子。 入力モードのIDと同一である必要はない。|省略した場合は、bundle idと入力モードのIDから自動で決められる。 |
TISIntendedLanguage | 必須 | どの言語の入力モードか。 |
tsInputModePrimaryInScriptKey | 必須 | |使用する文字体系を指定する (例: 日本語ならsmJapanese)。どこで使われるかは不明。 |
tsInputModePrimaryInScriptKey | 必須 | この入力モードが、主となる文字体系か。どこで使われるかは不明。 |
tsInputModeMenuIconFileKey | 必須 | 入力モードに対するアイコン |
tsInputModeAlternateMenuIconFileKey | 必須 | メニューバーでクリックされたときのアイコン |
tsInputModeDefaultStateKey | 必須 | 設定画面で言語を選んだときに自動で選択されるか。(と書いてあるがよくわからない) |
tsInputModeKeyEquivalentKey | 任意 | この入力モードに切り替えるために使うキー |
tsInputModeKeyEquivalentModifiersKey | 任意 | この入力モードに切り替えるために使う修飾キー |
tsInputModeJISKeyboardShortcutKey | 任意 | この入力モードに切り替えるために使うキー。(JISキーボード用)(0=none,1=hiragana,2=katakana,3=eisu) |
これらをふまえてEmojiIMでは以下のように定義した。
<key>ComponentInputModeDict</key> <dict> <key>tsInputModeListKey</key> <dict> <key>jp.mzp.inputmethod.EmojiIM</key> <dict> <key>TISInputSourceID</key> <string>jp.mzp.inputmethod.EmojiIM.emoji</string> <key>TISIntendedLanguage</key> <string>en</string> <key>tsInputModeScriptKey</key> <string>smUnicode</string> <key>tsInputModeMenuIconFileKey</key> <string>InputMethodIcon.tiff</string> <key>tsInputModeAlternateMenuIconFileKey</key> <string>InputMethodIcon.tiff</string> <key>tsInputModeDefaultStateKey</key> <true/> </dict> <key>com.apple.inputmethod.Roman</key> <dict> <key>TISInputSourceID</key> <string>jp.mzp.inputmethod.EmojiIM.roman</string> <key>TISIntendedLanguage</key> <string>en</string> <key>tsInputModeScriptKey</key> <string>smRoman</string> <key>tsInputModeMenuIconFileKey</key> <string>InputMethodIcon.tiff</string> <key>tsInputModeAlternateMenuIconFileKey</key> <string>InputMethodIcon.tiff</string> <key>tsInputModeDefaultStateKey</key> <true/> </dict> </dict> <key>tsVisibleInputModeOrderedArrayKey</key> <array> <string>jp.mzp.inputmethod.EmojiIM</string> <string>com.apple.inputmethod.Roman</string> </array> </dict>
これで設定画面より入力モードの追加・削除ができる。
追加後はメニューバーから入力モードが切り替えられる。
🌐 入力モードの名前
設定画面に入力モードIDがそのまま表示されるのは分かりづらいので、分かりやすい名前をつける。
これはローカライゼーションの仕組みを用いて行なう。XcodeでInfoPlist.stringsを追加し以下のように定義する。
CFBundleName = "Emoji IM"; com.apple.inputmethod.Roman = "Emoji(Alphabet)"; jp.mzp.inputmethod.EmojiIM = "Emoji";
これで入力モードの名前を指定できる。

🔀入力コントローラでのモード切り替え
入力モードを切り替えた場合は、入力コントローラの setValue:forTag:client:
が呼ばれる。
アルファベット入力モードかどうかを示すdirectMode変数の値を変更するようにした。
class EmojiInputController: IMKInputController { private var directMode: Bool = false override func setValue(_ value: Any, forTag tag: Int, client sender: Any) { // valueに入力モードIDが渡されるので、動作を切り替える guard let value = value as? NSString else { return } directMode = value == "com.apple.inputmethod.Roman" } }
キー入力のハンドラでは、directMode変数に基づいて処理を決める。
class EmojiInputController: IMKInputController { override func handle(_ event: NSEvent, client sender: Any) -> Bool { NSLog("%@", "\(#function)((\(event), client: \(sender))") if directMode { // directModeが真ならfalseを返し、通常の処理を行なうようにする return false } // 通常の処理 } }