From b03670cbcfaa3ca556bbbb7b8293e2104f529d49 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 10 Feb 2023 21:38:11 +0800 Subject: [PATCH] InputHandler // Implementing Hanin Keyboard Symbol Input support. --- Source/Modules/InputHandler_Core.swift | 6 +++ .../InputHandler_HandleCandidate.swift | 17 +++++-- Source/Modules/InputHandler_HandleEvent.swift | 22 +++++++- Source/Modules/InputHandler_HandleInput.swift | 19 +++++-- .../Modules/InputHandler_HandleStates.swift | 50 +++++++++++++++++++ .../Resources/Base.lproj/Localizable.strings | 1 + Source/Resources/en.lproj/Localizable.strings | 1 + Source/Resources/ja.lproj/Localizable.strings | 1 + .../zh-Hans.lproj/Localizable.strings | 1 + .../zh-Hant.lproj/Localizable.strings | 1 + 10 files changed, 109 insertions(+), 10 deletions(-) diff --git a/Source/Modules/InputHandler_Core.swift b/Source/Modules/InputHandler_Core.swift index 525687bd..1a3ab3d2 100644 --- a/Source/Modules/InputHandler_Core.swift +++ b/Source/Modules/InputHandler_Core.swift @@ -111,6 +111,12 @@ public class InputHandler: InputHandlerProtocol { isCodePointInputMode = false } + // MARK: - Hanin Keyboard Symbol Mode. + + var isHaninKeyboardSymbolMode = false + + static let tooltipHaninKeyboardSymbolMode: String = "\("Hanin Keyboard Symbol Input.".localized)  " + // MARK: - Codepoint Input Buffer. var isCodePointInputMode = false { diff --git a/Source/Modules/InputHandler_HandleCandidate.swift b/Source/Modules/InputHandler_HandleCandidate.swift index 3a53ace1..858daf50 100644 --- a/Source/Modules/InputHandler_HandleCandidate.swift +++ b/Source/Modules/InputHandler_HandleCandidate.swift @@ -198,11 +198,18 @@ extension InputHandler { // MARK: - Flipping pages by using symbol menu keys (when they are not occupied). if input.isSymbolMenuPhysicalKey { - var updated = true - let reverseTrigger = input.isShiftHold || input.isOptionHold - updated = reverseTrigger ? ctlCandidate.showPreviousLine() : ctlCandidate.showNextLine() - if !updated { delegate.callError("66F3477B") } - return true + switch input.modifierFlags { + case .shift, [], + .option where state.type != .ofSymbolTable: + var updated = true + let reverseTrigger = input.isShiftHold || input.isOptionHold + updated = reverseTrigger ? ctlCandidate.showPreviousLine() : ctlCandidate.showNextLine() + if !updated { delegate.callError("66F3477B") } + return true + case .option where state.type == .ofSymbolTable: + return handleHaninKeyboardSymbolModeToggle() + default: break + } } delegate.callError("172A0F81") diff --git a/Source/Modules/InputHandler_HandleEvent.swift b/Source/Modules/InputHandler_HandleEvent.swift index 534807b7..5a44ac5b 100644 --- a/Source/Modules/InputHandler_HandleEvent.swift +++ b/Source/Modules/InputHandler_HandleEvent.swift @@ -73,8 +73,26 @@ extension InputHandler { } 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) + case .horizontal: + switch event.modifierFlags { + case []: imkC.moveDown(self) + case .shift, + .option where delegate.state.type != .ofSymbolTable: + imkC.moveUp(self) + case .option where delegate.state.type == .ofSymbolTable: + handleHaninKeyboardSymbolModeToggle() + default: break + } + case .vertical: + switch event.modifierFlags { + case []: imkC.moveRight(self) + case .shift, + .option where delegate.state.type != .ofSymbolTable: + imkC.moveLeft(self) + case .option where delegate.state.type == .ofSymbolTable: + handleHaninKeyboardSymbolModeToggle() + default: break + } @unknown default: break } return true diff --git a/Source/Modules/InputHandler_HandleInput.swift b/Source/Modules/InputHandler_HandleInput.swift index 45456360..fabd451c 100644 --- a/Source/Modules/InputHandler_HandleInput.swift +++ b/Source/Modules/InputHandler_HandleInput.swift @@ -100,9 +100,13 @@ extension InputHandler { delegate.switchState(state.convertedToInputting) } - // MARK: 注音按鍵輸入處理 (Handle BPMF Keys) + // MARK: 注音按鍵輸入與漢音鍵盤符號輸入處理 (Handle BPMF Keys & Hanin Keyboard Symbol Input) - if let compositionHandled = handleComposition(input: input) { return compositionHandled } + if isHaninKeyboardSymbolMode, input.modifierFlags.isEmpty || input.modifierFlags == .shift { + return handleHaninKeyboardSymbolModeInput(input: input) + } else if let compositionHandled = handleComposition(input: input) { + return compositionHandled + } // MARK: 用上下左右鍵呼叫選字窗 (Calling candidate window using Up / Down or PageUp / PageDn.) @@ -165,7 +169,16 @@ extension InputHandler { case [.option, .shift]: return handlePunctuationList(alternative: true, isJIS: isJIS) case .option: - return handleCodePointInputToggle() + switch (isCodePointInputMode, isHaninKeyboardSymbolMode) { + case (false, false): return handleCodePointInputToggle() + case (true, false): + handleCodePointInputToggle() + return handleHaninKeyboardSymbolModeToggle() + case (false, true): + return handleHaninKeyboardSymbolModeToggle() + default: break + } + return true default: break } case .kSpace: // 倘若沒有在偏好設定內將 Space 空格鍵設為選字窗呼叫用鍵的話……… diff --git a/Source/Modules/InputHandler_HandleStates.swift b/Source/Modules/InputHandler_HandleStates.swift index c1f14e31..168ff99c 100644 --- a/Source/Modules/InputHandler_HandleStates.swift +++ b/Source/Modules/InputHandler_HandleStates.swift @@ -293,6 +293,7 @@ extension InputHandler { guard let delegate = delegate else { return false } let state = delegate.state + if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() } if isCodePointInputMode { return handleCodePointInputToggle() } guard state.type == .ofInputting else { return false } @@ -474,6 +475,7 @@ extension InputHandler { guard let delegate = delegate else { return false } let state = delegate.state + if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() } if isCodePointInputMode { return handleCodePointInputToggle() } guard state.type == .ofInputting else { return false } @@ -572,6 +574,7 @@ extension InputHandler { guard let delegate = delegate else { return false } let state = delegate.state + if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() } if isCodePointInputMode { return handleCodePointInputToggle() } guard state.type == .ofInputting else { return false } @@ -813,6 +816,53 @@ extension InputHandler { return true } + // MARK: - 處理漢音鍵盤符號輸入狀態的啟動過程 + + @discardableResult func handleHaninKeyboardSymbolModeToggle() -> Bool { + guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false } + if isHaninKeyboardSymbolMode { + isHaninKeyboardSymbolMode = false + delegate.switchState(IMEState.ofAbortion()) + return true + } + var updatedState = generateStateOfInputting(sansReading: true) + delegate.switchState(IMEState.ofCommitting(textToCommit: updatedState.displayedText)) + updatedState = IMEState.ofEmpty() + updatedState.tooltipDuration = 0 + updatedState.tooltip = Self.tooltipHaninKeyboardSymbolMode + delegate.switchState(updatedState) + isHaninKeyboardSymbolMode = true + return true + } + + /// 處理漢音鍵盤符號輸入。 + /// - Parameters: + /// - input: 輸入按鍵訊號。 + /// - Returns: 將按鍵行為「是否有處理掉」藉由 SessionCtl 回報給 IMK。 + func handleHaninKeyboardSymbolModeInput(input: InputSignalProtocol) -> Bool { + guard let delegate = delegate, delegate.state.type != .ofDeactivated else { return false } + let charText = input.text.lowercased().applyingTransformFW2HW(reverse: false) + guard CandidateNode.mapHaninKeyboardSymbols.keys.contains(charText) else { + return handleHaninKeyboardSymbolModeToggle() + } + guard + charText.count == 1, let symbols = CandidateNode.queryHaninKeyboardSymbols(char: charText) + else { + delegate.callError("C1A760C7") + return true + } + // 得在這裡先 commit buffer,不然會導致「在摁 ESC 離開符號選單時會重複輸入上一次的組字區的內容」的不當行為。 + let textToCommit = generateStateOfInputting(sansReading: true).displayedText + delegate.switchState(IMEState.ofCommitting(textToCommit: textToCommit)) + if symbols.members.count == 1 { + delegate.switchState(IMEState.ofCommitting(textToCommit: symbols.members.map(\.name).joined())) + } else { + delegate.switchState(IMEState.ofSymbolTable(node: symbols)) + } + isHaninKeyboardSymbolMode = false // 用完就關掉,但保持選字窗開啟,所以這裡不用呼叫 toggle 函式。 + return true + } + // MARK: - 處理符號選單 /// 處理符號選單。 diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 0b9db99a..78012142 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -1,4 +1,5 @@ "vChewing" = "vChewing"; +"Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input."; "Open App Support Folder" = "Open App Support Folder"; "Invalid Code Point." = "Invalid Code Point."; "Code Point Input Mode." = "Code Point Input Mode."; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 0b9db99a..78012142 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -1,4 +1,5 @@ "vChewing" = "vChewing"; +"Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input."; "Open App Support Folder" = "Open App Support Folder"; "Invalid Code Point." = "Invalid Code Point."; "Code Point Input Mode." = "Code Point Input Mode."; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index b2fb27dd..673a2e27 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -1,4 +1,5 @@ "vChewing" = "威注音入力アプリ"; +"Hanin Keyboard Symbol Input." = "漢音キーボード符号入力。"; "Open App Support Folder" = "App Support フォルダーを開く"; "Invalid Code Point." = "コードポイントは正しくない。"; "Code Point Input Mode." = "コードポイント入力。"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index d36431c9..30648ac3 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -1,4 +1,5 @@ "vChewing" = "威注音输入法"; +"Hanin Keyboard Symbol Input." = "汉音键盘符号模式。"; "Open App Support Folder" = "开启 App Support 目录"; "Invalid Code Point." = "内码不正确。"; "Code Point Input Mode." = "内码输入模式。"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index fd32b057..c9f42524 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -1,4 +1,5 @@ "vChewing" = "威注音輸入法"; +"Hanin Keyboard Symbol Input." = "漢音鍵盤符號模式。"; "Open App Support Folder" = "開啟 App Support 目錄"; "Invalid Code Point." = "內碼不正確。"; "Code Point Input Mode." = "內碼輸入模式。";