InputHandler // Implementing Hanin Keyboard Symbol Input support.
This commit is contained in:
parent
86b85b9c83
commit
b03670cbcf
|
@ -111,6 +111,12 @@ public class InputHandler: InputHandlerProtocol {
|
||||||
isCodePointInputMode = false
|
isCodePointInputMode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Hanin Keyboard Symbol Mode.
|
||||||
|
|
||||||
|
var isHaninKeyboardSymbolMode = false
|
||||||
|
|
||||||
|
static let tooltipHaninKeyboardSymbolMode: String = "\("Hanin Keyboard Symbol Input.".localized) "
|
||||||
|
|
||||||
// MARK: - Codepoint Input Buffer.
|
// MARK: - Codepoint Input Buffer.
|
||||||
|
|
||||||
var isCodePointInputMode = false {
|
var isCodePointInputMode = false {
|
||||||
|
|
|
@ -198,11 +198,18 @@ extension InputHandler {
|
||||||
// MARK: - Flipping pages by using symbol menu keys (when they are not occupied).
|
// MARK: - Flipping pages by using symbol menu keys (when they are not occupied).
|
||||||
|
|
||||||
if input.isSymbolMenuPhysicalKey {
|
if input.isSymbolMenuPhysicalKey {
|
||||||
var updated = true
|
switch input.modifierFlags {
|
||||||
let reverseTrigger = input.isShiftHold || input.isOptionHold
|
case .shift, [],
|
||||||
updated = reverseTrigger ? ctlCandidate.showPreviousLine() : ctlCandidate.showNextLine()
|
.option where state.type != .ofSymbolTable:
|
||||||
if !updated { delegate.callError("66F3477B") }
|
var updated = true
|
||||||
return 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")
|
delegate.callError("172A0F81")
|
||||||
|
|
|
@ -73,8 +73,26 @@ extension InputHandler {
|
||||||
} else if event.isSymbolMenuPhysicalKey {
|
} else if event.isSymbolMenuPhysicalKey {
|
||||||
// 符號鍵的行為是固定的,不受偏好設定影響。
|
// 符號鍵的行為是固定的,不受偏好設定影響。
|
||||||
switch imkC.currentLayout {
|
switch imkC.currentLayout {
|
||||||
case .horizontal: _ = event.isShiftHold ? imkC.moveUp(self) : imkC.moveDown(self)
|
case .horizontal:
|
||||||
case .vertical: _ = event.isShiftHold ? imkC.moveLeft(self) : imkC.moveRight(self)
|
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
|
@unknown default: break
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -100,9 +100,13 @@ extension InputHandler {
|
||||||
delegate.switchState(state.convertedToInputting)
|
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.)
|
// MARK: 用上下左右鍵呼叫選字窗 (Calling candidate window using Up / Down or PageUp / PageDn.)
|
||||||
|
|
||||||
|
@ -165,7 +169,16 @@ extension InputHandler {
|
||||||
case [.option, .shift]:
|
case [.option, .shift]:
|
||||||
return handlePunctuationList(alternative: true, isJIS: isJIS)
|
return handlePunctuationList(alternative: true, isJIS: isJIS)
|
||||||
case .option:
|
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
|
default: break
|
||||||
}
|
}
|
||||||
case .kSpace: // 倘若沒有在偏好設定內將 Space 空格鍵設為選字窗呼叫用鍵的話………
|
case .kSpace: // 倘若沒有在偏好設定內將 Space 空格鍵設為選字窗呼叫用鍵的話………
|
||||||
|
|
|
@ -293,6 +293,7 @@ extension InputHandler {
|
||||||
guard let delegate = delegate else { return false }
|
guard let delegate = delegate else { return false }
|
||||||
let state = delegate.state
|
let state = delegate.state
|
||||||
|
|
||||||
|
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||||
|
|
||||||
guard state.type == .ofInputting else { return false }
|
guard state.type == .ofInputting else { return false }
|
||||||
|
@ -474,6 +475,7 @@ extension InputHandler {
|
||||||
guard let delegate = delegate else { return false }
|
guard let delegate = delegate else { return false }
|
||||||
let state = delegate.state
|
let state = delegate.state
|
||||||
|
|
||||||
|
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||||
|
|
||||||
guard state.type == .ofInputting else { return false }
|
guard state.type == .ofInputting else { return false }
|
||||||
|
@ -572,6 +574,7 @@ extension InputHandler {
|
||||||
guard let delegate = delegate else { return false }
|
guard let delegate = delegate else { return false }
|
||||||
let state = delegate.state
|
let state = delegate.state
|
||||||
|
|
||||||
|
if isHaninKeyboardSymbolMode { return handleHaninKeyboardSymbolModeToggle() }
|
||||||
if isCodePointInputMode { return handleCodePointInputToggle() }
|
if isCodePointInputMode { return handleCodePointInputToggle() }
|
||||||
|
|
||||||
guard state.type == .ofInputting else { return false }
|
guard state.type == .ofInputting else { return false }
|
||||||
|
@ -813,6 +816,53 @@ extension InputHandler {
|
||||||
return true
|
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: - 處理符號選單
|
// MARK: - 處理符號選單
|
||||||
|
|
||||||
/// 處理符號選單。
|
/// 處理符號選單。
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"vChewing" = "vChewing";
|
"vChewing" = "vChewing";
|
||||||
|
"Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input.";
|
||||||
"Open App Support Folder" = "Open App Support Folder";
|
"Open App Support Folder" = "Open App Support Folder";
|
||||||
"Invalid Code Point." = "Invalid Code Point.";
|
"Invalid Code Point." = "Invalid Code Point.";
|
||||||
"Code Point Input Mode." = "Code Point Input Mode.";
|
"Code Point Input Mode." = "Code Point Input Mode.";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"vChewing" = "vChewing";
|
"vChewing" = "vChewing";
|
||||||
|
"Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input.";
|
||||||
"Open App Support Folder" = "Open App Support Folder";
|
"Open App Support Folder" = "Open App Support Folder";
|
||||||
"Invalid Code Point." = "Invalid Code Point.";
|
"Invalid Code Point." = "Invalid Code Point.";
|
||||||
"Code Point Input Mode." = "Code Point Input Mode.";
|
"Code Point Input Mode." = "Code Point Input Mode.";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"vChewing" = "威注音入力アプリ";
|
"vChewing" = "威注音入力アプリ";
|
||||||
|
"Hanin Keyboard Symbol Input." = "漢音キーボード符号入力。";
|
||||||
"Open App Support Folder" = "App Support フォルダーを開く";
|
"Open App Support Folder" = "App Support フォルダーを開く";
|
||||||
"Invalid Code Point." = "コードポイントは正しくない。";
|
"Invalid Code Point." = "コードポイントは正しくない。";
|
||||||
"Code Point Input Mode." = "コードポイント入力。";
|
"Code Point Input Mode." = "コードポイント入力。";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"vChewing" = "威注音输入法";
|
"vChewing" = "威注音输入法";
|
||||||
|
"Hanin Keyboard Symbol Input." = "汉音键盘符号模式。";
|
||||||
"Open App Support Folder" = "开启 App Support 目录";
|
"Open App Support Folder" = "开启 App Support 目录";
|
||||||
"Invalid Code Point." = "内码不正确。";
|
"Invalid Code Point." = "内码不正确。";
|
||||||
"Code Point Input Mode." = "内码输入模式。";
|
"Code Point Input Mode." = "内码输入模式。";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"vChewing" = "威注音輸入法";
|
"vChewing" = "威注音輸入法";
|
||||||
|
"Hanin Keyboard Symbol Input." = "漢音鍵盤符號模式。";
|
||||||
"Open App Support Folder" = "開啟 App Support 目錄";
|
"Open App Support Folder" = "開啟 App Support 目錄";
|
||||||
"Invalid Code Point." = "內碼不正確。";
|
"Invalid Code Point." = "內碼不正確。";
|
||||||
"Code Point Input Mode." = "內碼輸入模式。";
|
"Code Point Input Mode." = "內碼輸入模式。";
|
||||||
|
|
Loading…
Reference in New Issue