macOS Swift

参考資料

実装例

Tips

  • IMKCandidatesは色々と壊れている(# ゚Д゚)
  • カーソルの画面上の位置(座標)を知りたい
    • たとえば、自作変換候補ウィンドウをカーソルのそばに表示したいときなど
    • 方法1: この方法は一部のネイティブCocoaアプリケーションでしか動作しないので、方法2推奨
      • クライアント(IMKTextInput)のselectedRangeを取得して、それをNSRectに変換することでx, y, w, hが取得できる(kekeho)
      •   	...省略
          	func getCursorPos() -> NSRect {
          		let selectedRange = self.client().selectedRange()
          		return self.client().firstRect(forCharacterRange: selectedRange, actualRange: nil)
          	}
          }
    • 方法2
  • insertText(_ string: Any!, replacementRange: NSRange)の仕様
    • 文字の置換(挿入)
    • string: String, NSString, NSAttributedStringなど
    • replacementRange: NSRange位置のテキストを置換する
      • locationがNSNotFoundの場合: カーソル位置指定
      • lengthがNSNotFoundの場合: Not置換、挿入になる
  • setMarkedText(_ string: Any!, selectionRange: NSRange, replacementRange: NSRange)の仕様
    • 未確定文字列の置換(挿入)
    • string: String, NSString, NSAttributedStringなど
  • 未確定文字列の一部を選択(色付け)するには? (変換候補選択などで”となりのいぬ”の”いぬ”だけを色付けしたいときがある)
    • こういう感じのをつくりたいとき:
    • AttributedStringをつかってハイライトをつける
    • これが参考になる: https://github.com/google/mozc/blob/f3514b090743d23fdcc6824b7af4be4acda283fb/src/mac/GoogleJapaneseInputController.mm#L679
    • Swiftで書くとこんな感じ
      •   let hIdx = 0  // ハイライトしたいインデックス。「となりの」だけをハイライトしたい
          
          let attrMarkedText = NSMutableAttributedString()
          
          for (i, text) in texts.enumerated() {
              let attrText = NSMutableAttributedString(string: text)
              let attr: [AnyHashable: Any]
              if i == hIdx {
                  // Hilight
                  attr = self.mark(forStyle: kTSMHiliteSelectedConvertedText, at: NSMakeRange(0, NSNotFound))
              } else {
                  // Underline
                  attr = self.mark(forStyle: kTSMHiliteConvertedText, at: NSRange(location: 0, length: attrText.length))
                  
              }
              if let attr = attr as? [NSAttributedString.Key : Any] {
                  attrText.addAttributes(attr, range: NSRange(location: 0, length: attrText.length))
              }
              attrMarkedText.append(attrText)
          }
          
          self.client().setMarkedText(attrMarkedText, selectionRange: cursorPosition, replacementRange: cursorPosition)
  • 自前で変換候補ウィンドウを作って表示するときのNSWindow
  • 連続的にclientのinsertTextを追記で呼び出すと、たまに文字が吹き飛ぶ・前後する
    •   for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
        	self.client().insertText(String(c), replacementRange: range)
        }
        // クライアントアプリの画面に表示される文字列は「AGHDEFIJKLMNOPQRSTUVWXYZ」みたいなことになる
    • クライアントも非同期的に処理していると思われる(kekeho)
    • ある程度はまとめて書き込んでやったほうがよさそう(kekeho)
    • OTのテクニックが使えないか?

  • MacのChromeでGoogle Docsを開くと、変換候補ウィンドウの位置が狂う
    • Google日本語入力やAppleの純正IMEでもそうなる