From 0ce0604c1641b3f4694349700769c8db13e24350 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 24 Sep 2022 11:30:40 +0800 Subject: [PATCH] IMKCandidates // Move its key handling process to ctlIME. --- .../UIModules/CandidateUI/ctlCandidate.swift | 2 - .../CandidateUI/ctlCandidateIMK.swift | 68 ----------------- Source/Modules/ctlInputMethod_Core.swift | 2 +- Source/Modules/ctlInputMethod_Delegates.swift | 11 --- .../Modules/ctlInputMethod_HandleEvent.swift | 76 +++++++++++++++++-- 5 files changed, 69 insertions(+), 90 deletions(-) diff --git a/Source/Modules/UIModules/CandidateUI/ctlCandidate.swift b/Source/Modules/UIModules/CandidateUI/ctlCandidate.swift index 29434ccc..49479bb7 100644 --- a/Source/Modules/UIModules/CandidateUI/ctlCandidate.swift +++ b/Source/Modules/UIModules/CandidateUI/ctlCandidate.swift @@ -25,8 +25,6 @@ public class CandidateKeyLabel: NSObject { } public protocol ctlCandidateDelegate: AnyObject { - var isAssociatedPhrasesState: Bool { get } - func sharedEventHandler(_ event: NSEvent) -> Bool func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)] func ctlCandidate(_ controller: ctlCandidateProtocol, candidateAtIndex index: Int) diff --git a/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift b/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift index 35d360f3..8ad1fa85 100644 --- a/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift +++ b/Source/Modules/UIModules/CandidateUI/ctlCandidateIMK.swift @@ -185,74 +185,6 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol { setCandidateFrameTopLeft(adjustedPoint) } - - override public func interpretKeyEvents(_ eventArray: [NSEvent]) { - // 鬼知道為什麼這個函式接收的參數是陣列,但經過測試卻發現這個函式收到的陣列往往內容只有一個。 - // 這也可能是 Objective-C 當中允許接收內容為 nil 的一種方式。 - guard !eventArray.isEmpty else { return } - let event = eventArray[0] - guard let delegate = delegate else { return } - if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) { - _ = delegate.sharedEventHandler(event) - } else if event.isSymbolMenuPhysicalKey { - // 符號鍵的行為是固定的,不受偏好設定影響。 - switch currentLayout { - case .horizontal: event.isShiftHold ? moveUp(self) : moveDown(self) - case .vertical: event.isShiftHold ? moveLeft(self) : moveRight(self) - } - } else if event.isSpace { - switch PrefMgr.shared.specifyShiftSpaceKeyBehavior { - case true: _ = event.isShiftHold ? highlightNextCandidate() : showNextPage() - case false: _ = event.isShiftHold ? showNextPage() : highlightNextCandidate() - } - } else if event.isTab { - switch PrefMgr.shared.specifyShiftTabKeyBehavior { - case true: _ = event.isShiftHold ? showPreviousPage() : showNextPage() - case false: _ = event.isShiftHold ? highlightPreviousCandidate() : highlightNextCandidate() - } - } else { - if let newChar = Self.defaultIMKSelectionKey[event.keyCode] { - /// 根據 KeyCode 重新換算一下選字鍵的 NSEvent,糾正其 Character 數值。 - /// 反正 IMK 選字窗目前也沒辦法修改選字鍵。 - let newEvent = event.reinitiate(characters: newChar) - if let newEvent = newEvent { - if PrefMgr.shared.useSCPCTypingMode, delegate.isAssociatedPhrasesState { - // 註:input.isShiftHold 已經在 ctlInputMethod.handle() 內處理,因為在那邊處理才有效。 - if !event.isShiftHold { - _ = delegate.sharedEventHandler(event) - return - } - } else { - if #available(macOS 10.14, *) { - handleKeyboardEvent(newEvent) - } else { - super.interpretKeyEvents([newEvent]) - } - return - } - } - } - - if PrefMgr.shared.useSCPCTypingMode, !event.isReservedKey { - _ = delegate.sharedEventHandler(event) - return - } - - if delegate.isAssociatedPhrasesState, - !event.isPageUp, !event.isPageDown, !event.isCursorForward, !event.isCursorBackward, - !event.isCursorClockLeft, !event.isCursorClockRight, !event.isSpace, - !event.isEnter || !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter - { - _ = delegate.sharedEventHandler(event) - return - } - super.interpretKeyEvents(eventArray) - } - } - - public func superInterpretKeyEvents(_ eventArray: [NSEvent]) { - super.interpretKeyEvents(eventArray) - } } // MARK: - Generate TISInputSource Object diff --git a/Source/Modules/ctlInputMethod_Core.swift b/Source/Modules/ctlInputMethod_Core.swift index 17667e37..9796eca9 100644 --- a/Source/Modules/ctlInputMethod_Core.swift +++ b/Source/Modules/ctlInputMethod_Core.swift @@ -322,7 +322,7 @@ class ctlInputMethod: IMKInputController { Self.areWeNerfing = eventToDeal.modifierFlags.contains([.shift, .command]) // IMK 選字窗處理,當且僅當啟用了 IMK 選字窗的時候才會生效。 - if let result = imkCandidatesEventHandler(event: eventToDeal) { + if let result = imkCandidatesEventPreHandler(event: eventToDeal) { if shouldUseShiftToggleHandle { rencentKeyHandledByKeyHandlerEtc = result } diff --git a/Source/Modules/ctlInputMethod_Delegates.swift b/Source/Modules/ctlInputMethod_Delegates.swift index 0b3821ba..6e1c45cf 100644 --- a/Source/Modules/ctlInputMethod_Delegates.swift +++ b/Source/Modules/ctlInputMethod_Delegates.swift @@ -50,17 +50,6 @@ extension ctlInputMethod: KeyHandlerDelegate { // MARK: - Candidate Controller Delegate extension ctlInputMethod: ctlCandidateDelegate { - var isAssociatedPhrasesState: Bool { state.type == .ofAssociates } - - /// 完成 handle() 函式本該完成的內容,但去掉了與 IMK 選字窗有關的判斷語句。 - /// 這樣分開處理很有必要,不然 handle() 函式會陷入無限迴圈。 - /// 該函式僅由 IMK 選字窗來存取,且對接給 commonEventHandler()。 - /// - Parameter event: 由 IMK 選字窗接收的裝置操作輸入事件。 - /// - Returns: 回「`true`」以將該案件已攔截處理的訊息傳遞給 IMK;回「`false`」則放行、不作處理。 - @discardableResult func sharedEventHandler(_ event: NSEvent) -> Bool { - commonEventHandler(event) - } - func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int { _ = controller // 防止格式整理工具毀掉與此對應的參數。 if state.isCandidateContainer { diff --git a/Source/Modules/ctlInputMethod_HandleEvent.swift b/Source/Modules/ctlInputMethod_HandleEvent.swift index c4fb131a..e0fa6391 100644 --- a/Source/Modules/ctlInputMethod_HandleEvent.swift +++ b/Source/Modules/ctlInputMethod_HandleEvent.swift @@ -37,10 +37,10 @@ extension ctlInputMethod { /// 這樣分開處理很有必要,不然 handle() 函式會陷入無限迴圈。 /// - Parameter event: 由 IMK 選字窗接收的裝置操作輸入事件。 /// - Returns: 回「`true`」以將該案件已攔截處理的訊息傳遞給 IMK;回「`false`」則放行、不作處理。 - func imkCandidatesEventHandler(event eventToDeal: NSEvent) -> Bool? { + func imkCandidatesEventPreHandler(event eventToDeal: NSEvent) -> Bool? { // IMK 選字窗處理,當且僅當啟用了 IMK 選字窗的時候才會生效。 // 這樣可以讓 interpretKeyEvents() 函式自行判斷: - // - 是就地交給 super.interpretKeyEvents() 處理? + // - 是就地交給 imkCandidates.interpretKeyEvents() 處理? // - 還是藉由 delegate 扔回 ctlInputMethod 給 KeyHandler 處理? if let imkCandidates = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK, imkCandidates.visible { let event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: eventToDeal) ?? eventToDeal @@ -52,25 +52,85 @@ extension ctlInputMethod { NSSound.beep() return true } - imkCandidates.interpretKeyEvents([newEvent]) - return true + + return imkCandidatesEventSubHandler(event: newEvent) } // 聯想詞選字。 if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode], - event.isShiftHold, isAssociatedPhrasesState, + event.isShiftHold, state.type == .ofAssociates, let newEvent = event.reinitiate(modifierFlags: [], characters: newChar) { if #available(macOS 10.14, *) { imkCandidates.handleKeyboardEvent(newEvent) } else { - imkCandidates.superInterpretKeyEvents([newEvent]) + imkCandidates.interpretKeyEvents([newEvent]) } + return true } - imkCandidates.interpretKeyEvents([event]) - return true + return imkCandidatesEventSubHandler(event: event) } return nil } + + func imkCandidatesEventSubHandler(event: NSEvent) -> Bool { + let eventArray = [event] + guard let imkC = Self.ctlCandidateCurrent as? ctlCandidateIMK else { return false } + if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) { + return commonEventHandler(event) + } else if event.isSymbolMenuPhysicalKey { + // 符號鍵的行為是固定的,不受偏好設定影響。 + switch imkC.currentLayout { + case .horizontal: _ = event.isShiftHold ? imkC.moveUp(self) : imkC.moveDown(self) + case .vertical: _ = event.isShiftHold ? imkC.moveLeft(self) : imkC.moveRight(self) + } + return true + } else if event.isSpace { + switch PrefMgr.shared.specifyShiftSpaceKeyBehavior { + case true: _ = event.isShiftHold ? imkC.highlightNextCandidate() : imkC.showNextPage() + case false: _ = event.isShiftHold ? imkC.showNextPage() : imkC.highlightNextCandidate() + } + return true + } else if event.isTab { + switch PrefMgr.shared.specifyShiftTabKeyBehavior { + case true: _ = event.isShiftHold ? imkC.showPreviousPage() : imkC.showNextPage() + case false: _ = event.isShiftHold ? imkC.highlightPreviousCandidate() : imkC.highlightNextCandidate() + } + return true + } else { + if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode] { + /// 根據 KeyCode 重新換算一下選字鍵的 NSEvent,糾正其 Character 數值。 + /// 反正 IMK 選字窗目前也沒辦法修改選字鍵。 + let newEvent = event.reinitiate(characters: newChar) + if let newEvent = newEvent { + if PrefMgr.shared.useSCPCTypingMode, state.type == .ofAssociates { + // 註:input.isShiftHold 已經在 ctlInputMethod.handle() 內處理,因為在那邊處理才有效。 + return event.isShiftHold ? true : commonEventHandler(event) + } else { + if #available(macOS 10.14, *) { + imkC.handleKeyboardEvent(newEvent) + } else { + imkC.interpretKeyEvents([newEvent]) + } + return true + } + } + } + + if PrefMgr.shared.useSCPCTypingMode, !event.isReservedKey { + return commonEventHandler(event) + } + + if state.type == .ofAssociates, + !event.isPageUp, !event.isPageDown, !event.isCursorForward, !event.isCursorBackward, + !event.isCursorClockLeft, !event.isCursorClockRight, !event.isSpace, + !event.isEnter || !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter + { + return commonEventHandler(event) + } + imkC.interpretKeyEvents(eventArray) + return true + } + } }