From eab6402e31f6de5c055f85a7a0bcd3ab6c276ba0 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 13 Aug 2022 20:52:40 +0800 Subject: [PATCH] ctlIME // +isVerticalTyping() & guard-let the client(). --- .../ctlInputMethod_Core.swift | 36 ++++++++++--------- .../ctlInputMethod_Delegates.swift | 16 +++------ .../ctlInputMethod_HandleDisplay.swift | 6 ++-- .../ctlInputMethod_HandleStates.swift | 9 ++--- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Source/Modules/ControllerModules/ctlInputMethod_Core.swift b/Source/Modules/ControllerModules/ctlInputMethod_Core.swift index a9251fbf..022a7e30 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_Core.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_Core.swift @@ -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 // 無法列印的訊號輸入,一概不作處理。 diff --git a/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift b/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift index 6b7a47a4..57993eb1 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift @@ -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 // 無法列印的訊號輸入,一概不作處理。 diff --git a/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift b/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift index 2ee724b1..989a0e6e 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift @@ -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 diff --git a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift index 16f1028e..f8007559 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift @@ -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) ) }