From 53dc7cc74b87f650ee05cf70baf2534f327b25f4 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 14 Aug 2022 10:40:12 +0800 Subject: [PATCH] IMKCandidates // Handle InputState.AssociatedPhrases. --- .../ctlInputMethod_Delegates.swift | 7 ++- .../CandidateUI/ctlCandidateIMK.swift | 48 ++++++++++++------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift b/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift index c8c8b00f..17cdd209 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_Delegates.swift @@ -52,6 +52,10 @@ extension ctlInputMethod: KeyHandlerDelegate { extension ctlInputMethod: ctlCandidateDelegate { var isAssociatedPhrasesMode: Bool { state is InputState.AssociatedPhrases } + /// 與 handle() 完全雷同,但去掉了與 IMK 選字窗有關的判斷語句。 + /// 這兩個函數最好分開處理,不然 handle() 函數會陷入無限迴圈。 + /// - Parameter event: 由 IMK 選字窗接收的裝置操作輸入事件。 + /// - Returns: 回「`true`」以將該案件已攔截處理的訊息傳遞給 IMK;回「`false`」則放行、不作處理。 func handleDelegateEvent(_ event: NSEvent!) -> Bool { // 用 Shift 開關半形英數模式,僅對 macOS 10.15 及之後的 macOS 有效。 if #available(macOS 10.15, *) { @@ -100,7 +104,8 @@ extension ctlInputMethod: ctlCandidateDelegate { /// 將按鍵行為與當前輸入法狀態結合起來、交給按鍵調度模組來處理。 /// 再根據返回的 result bool 數值來告知 IMK「這個按鍵事件是被處理了還是被放行了」。 - let result = keyHandler.handleCandidate(state: state, input: input) { newState in + /// 這裡不用 keyHandler.handleCandidate() 是因為需要針對聯想詞輸入狀態做額外處理。 + let result = keyHandler.handle(input: input, state: state) { newState in self.handle(state: newState) } errorCallback: { clsSFX.beep() diff --git a/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift b/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift index 25c1e227..c221714a 100644 --- a/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift +++ b/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift @@ -244,6 +244,7 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol { // 鬼知道為什麼這個函式接收的參數是陣列,但經過測試卻發現這個函式收到的陣列往往內容只有一個。 // 這也可能是 Objective-C 當中允許接收內容為 nil 的一種方式。 guard !eventArray.isEmpty else { return } + var eventArray = eventArray let event = eventArray[0] let input = InputSignal(event: event) guard let delegate = delegate else { return } @@ -280,25 +281,36 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol { moveDown(self) } } - } else if let newChar = defaultIMKSelectionKey[event.keyCode] { - /// 根據 KeyCode 重新換算一下選字鍵的 NSEvent,糾正其 Character 數值。 - let newEvent = NSEvent.keyEvent( - with: event.type, - location: event.locationInWindow, - modifierFlags: event.modifierFlags, - timestamp: event.timestamp, - windowNumber: event.windowNumber, - context: nil, - characters: newChar, - charactersIgnoringModifiers: event.charactersIgnoringModifiers ?? event.characters ?? "", - isARepeat: event.isARepeat, - keyCode: event.keyCode - ) - if let newEvent = newEvent { - /// 這裡不用診斷了,檢出的內容都是經過轉換之後的正確 NSEvent。 - super.interpretKeyEvents([newEvent]) - } } else { + if let newChar = defaultIMKSelectionKey[event.keyCode] { + /// 根據 KeyCode 重新換算一下選字鍵的 NSEvent,糾正其 Character 數值。 + /// 反正 IMK 選字窗目前也沒辦法修改選字鍵。 + let newEvent = NSEvent.keyEvent( + with: event.type, + location: event.locationInWindow, + modifierFlags: event.modifierFlags, + timestamp: event.timestamp, + windowNumber: event.windowNumber, + context: nil, + characters: newChar, + charactersIgnoringModifiers: event.charactersIgnoringModifiers ?? event.characters ?? "", + isARepeat: event.isARepeat, + keyCode: event.keyCode + ) + if let newEvent = newEvent { + /// 這裡不用診斷了,檢出的內容都是經過轉換之後的正確 NSEvent。 + eventArray = Array(eventArray.dropFirst(0)) + eventArray.insert(newEvent, at: 0) + } + } + if delegate.isAssociatedPhrasesMode, + !input.isPageUp, !input.isPageDown, !input.isCursorForward, !input.isCursorBackward, + !input.isCursorClockLeft, !input.isCursorClockRight, !input.isSpace, + !input.isEnter || !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter + { + _ = delegate.handleDelegateEvent(event) + return + } super.interpretKeyEvents(eventArray) } }