ctlIME // +isVerticalTyping() & guard-let the client().
This commit is contained in:
parent
318f27ad19
commit
eab6402e31
|
@ -39,6 +39,15 @@ class ctlInputMethod: IMKInputController {
|
|||
var state: InputStateProtocol = InputState.Empty()
|
||||
/// 當前這個 ctlInputMethod 副本是否處於英數輸入模式。
|
||||
var isASCIIMode: Bool = false
|
||||
/// 記錄當前輸入環境是縱排輸入還是橫排輸入。
|
||||
public var isVerticalTyping: Bool {
|
||||
guard let client = client() else { return false }
|
||||
var textFrame = NSRect.zero
|
||||
let attributes: [AnyHashable: Any]? = client.attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
return (attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
}
|
||||
|
||||
/// 切換當前 ctlInputMethod 副本的英數輸入模式開關。
|
||||
func toggleASCIIMode() -> Bool {
|
||||
|
@ -54,7 +63,9 @@ class ctlInputMethod: IMKInputController {
|
|||
|
||||
/// 指定鍵盤佈局。
|
||||
func setKeyLayout() {
|
||||
client().overrideKeyboard(withKeyboardNamed: mgrPrefs.basicKeyboardLayout)
|
||||
if let client = client() {
|
||||
client.overrideKeyboard(withKeyboardNamed: mgrPrefs.basicKeyboardLayout)
|
||||
}
|
||||
}
|
||||
|
||||
/// 重設按鍵調度模組,會將當前尚未遞交的內容遞交出去。
|
||||
|
@ -95,7 +106,8 @@ class ctlInputMethod: IMKInputController {
|
|||
// 因為偶爾會收到與 activateServer 有關的以「強制拆 nil」為理由的報錯,
|
||||
// 所以這裡添加這句、來試圖應對這種情況。
|
||||
if keyHandler.delegate == nil { keyHandler.delegate = self }
|
||||
setValue(IME.currentInputMode.rawValue, forTag: 114_514, client: client())
|
||||
guard let client = client() else { return }
|
||||
setValue(IME.currentInputMode.rawValue, forTag: 114_514, client: client)
|
||||
keyHandler.clear() // 這句不要砍,因為後面 handle State.Empty() 不一定執行。
|
||||
keyHandler.ensureParser()
|
||||
|
||||
|
@ -111,7 +123,7 @@ class ctlInputMethod: IMKInputController {
|
|||
|
||||
/// 必須加上下述條件,否則會在每次切換至輸入法本體的視窗(比如偏好設定視窗)時會卡死。
|
||||
/// 這是很多 macOS 副廠輸入法的常見失誤之處。
|
||||
if client().bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
if client.bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
// 強制重設當前鍵盤佈局、使其與偏好設定同步。
|
||||
setKeyLayout()
|
||||
handle(state: InputState.Empty())
|
||||
|
@ -152,7 +164,7 @@ class ctlInputMethod: IMKInputController {
|
|||
keyHandler.inputMode = newInputMode
|
||||
/// 必須加上下述條件,否則會在每次切換至輸入法本體的視窗(比如偏好設定視窗)時會卡死。
|
||||
/// 這是很多 macOS 副廠輸入法的常見失誤之處。
|
||||
if client().bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
if let client = client(), client.bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
// 強制重設當前鍵盤佈局、使其與偏好設定同步。這裡的這一步也不能省略。
|
||||
setKeyLayout()
|
||||
handle(state: InputState.Empty())
|
||||
|
@ -221,24 +233,16 @@ class ctlInputMethod: IMKInputController {
|
|||
// 準備修飾鍵,用來判定要新增的詞彙是否需要賦以非常低的權重。
|
||||
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
|
||||
|
||||
var textFrame = NSRect.zero
|
||||
|
||||
let attributes: [AnyHashable: Any]? = client().attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
|
||||
let isTypingVertical =
|
||||
(attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
|
||||
if client().bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
if let client = client(),
|
||||
client.bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
{
|
||||
IME.areWeUsingOurOwnPhraseEditor = true
|
||||
} else {
|
||||
IME.areWeUsingOurOwnPhraseEditor = false
|
||||
}
|
||||
|
||||
var input = InputSignal(event: event, isVerticalTyping: isTypingVertical)
|
||||
var input = InputSignal(event: event, isVerticalTyping: isVerticalTyping)
|
||||
input.isASCIIModeInput = isASCIIMode
|
||||
|
||||
// 無法列印的訊號輸入,一概不作處理。
|
||||
|
|
|
@ -78,24 +78,16 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
// 準備修飾鍵,用來判定要新增的詞彙是否需要賦以非常低的權重。
|
||||
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
|
||||
|
||||
var textFrame = NSRect.zero
|
||||
|
||||
let attributes: [AnyHashable: Any]? = client().attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
|
||||
let isTypingVertical =
|
||||
(attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
|
||||
if client().bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
if let client = client(),
|
||||
client.bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
{
|
||||
IME.areWeUsingOurOwnPhraseEditor = true
|
||||
} else {
|
||||
IME.areWeUsingOurOwnPhraseEditor = false
|
||||
}
|
||||
|
||||
var input = InputSignal(event: event, isVerticalTyping: isTypingVertical)
|
||||
var input = InputSignal(event: event, isVerticalTyping: isVerticalTyping)
|
||||
input.isASCIIModeInput = isASCIIMode
|
||||
|
||||
// 無法列印的訊號輸入,一概不作處理。
|
||||
|
|
|
@ -15,13 +15,14 @@ import Foundation
|
|||
|
||||
extension ctlInputMethod {
|
||||
func show(tooltip: String, composingBuffer: String, cursorIndex: Int) {
|
||||
guard let client = client() else { return }
|
||||
var lineHeightRect = NSRect(x: 0.0, y: 0.0, width: 16.0, height: 16.0)
|
||||
var cursor = cursorIndex
|
||||
if cursor == composingBuffer.count, cursor != 0 {
|
||||
cursor -= 1
|
||||
}
|
||||
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 {
|
||||
client().attributes(
|
||||
client.attributes(
|
||||
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect
|
||||
)
|
||||
cursor -= 1
|
||||
|
@ -30,6 +31,7 @@ extension ctlInputMethod {
|
|||
}
|
||||
|
||||
func show(candidateWindowWith state: InputStateProtocol) {
|
||||
guard let client = client() else { return }
|
||||
var isTypingVertical: Bool {
|
||||
if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.isTypingVertical
|
||||
|
@ -153,7 +155,7 @@ extension ctlInputMethod {
|
|||
}
|
||||
|
||||
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 {
|
||||
client().attributes(
|
||||
client.attributes(
|
||||
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect
|
||||
)
|
||||
cursor -= 1
|
||||
|
|
|
@ -47,8 +47,9 @@ extension ctlInputMethod {
|
|||
|
||||
/// 針對受 .NotEmpty() 管轄的非空狀態,在組字區內顯示游標。
|
||||
private func setInlineDisplayWithCursor() {
|
||||
guard let client = client() else { return }
|
||||
if let state = state as? InputState.AssociatedPhrases {
|
||||
client().setMarkedText(
|
||||
client.setMarkedText(
|
||||
state.attributedString, selectionRange: NSRange(location: 0, length: 0),
|
||||
replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
|
@ -94,7 +95,7 @@ extension ctlInputMethod {
|
|||
/// 所謂選區「selectionRange」,就是「可見游標位置」的位置,只不過長度
|
||||
/// 是 0 且取代範圍(replacementRange)為「NSNotFound」罷了。
|
||||
/// 也就是說,內文組字區該在哪裡出現,得由客體軟體來作主。
|
||||
client().setMarkedText(
|
||||
client.setMarkedText(
|
||||
state.attributedString, selectionRange: NSRange(location: state.cursorIndex, length: 0),
|
||||
replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
|
@ -113,12 +114,12 @@ extension ctlInputMethod {
|
|||
/// 遞交組字區內容。
|
||||
/// 注意:必須在 IMK 的 commitComposition 函式當中也間接或者直接執行這個處理。
|
||||
private func commit(text: String) {
|
||||
guard let client = client() else { return }
|
||||
let buffer = IME.kanjiConversionIfRequired(text)
|
||||
if buffer.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
client().insertText(
|
||||
client.insertText(
|
||||
buffer, replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue