IMKCandidates // Dissolve InputHandler.handleEvent(), etc.

This commit is contained in:
ShikiSuen 2023-06-24 14:19:33 +08:00
parent 8dc7c027fc
commit 6c87a29fb0
8 changed files with 97 additions and 214 deletions

View File

@ -29,7 +29,7 @@ public protocol InputHandlerProtocol {
func clear()
func clearComposerAndCalligrapher()
func ensureKeyboardParser()
func handleEvent(_ event: NSEvent) -> Bool
func triageInput(event input: InputSignalProtocol) -> Bool
func generateStateOfCandidates() -> IMEStateProtocol
func generateStateOfInputting(sansReading: Bool) -> IMEStateProtocol
func generateStateOfAssociates(withPair pair: Megrez.KeyValuePaired) -> IMEStateProtocol

View File

@ -22,7 +22,13 @@ extension InputHandler {
guard let delegate = delegate else { return false }
guard var ctlCandidate = delegate.candidateController() else { return false }
let state = delegate.state
guard state.isCandidateContainer, !state.candidates.isEmpty else { return false }
guard state.isCandidateContainer else { return false } // isEmpty
guard ctlCandidate.visible else { return false }
var input = input
var imkC: CtlCandidateIMK? {
prefs.useIMKCandidateWindow ? (ctlCandidate as? CtlCandidateIMK) : nil
}
// MARK: 使
@ -85,6 +91,14 @@ extension InputHandler {
// MARK:
func confirmHighlightedCandidate() {
if let imkC = imkC, let enterEvent = KeyCode.kCarriageReturn.toEvent() {
imkC.process(event: enterEvent)
} else {
delegate.candidateSelectionConfirmedByInputHandler(at: ctlCandidate.highlightedIndex)
}
}
if let keyCodeType = KeyCode(rawValue: input.keyCode) {
switch keyCodeType {
case .kLineFeed, .kCarriageReturn:
@ -92,7 +106,7 @@ extension InputHandler {
delegate.switchState(IMEState.ofAbortion())
return true
}
delegate.candidateSelectionConfirmedByInputHandler(at: ctlCandidate.highlightedIndex)
confirmHighlightedCandidate()
return true
case .kTab:
let updated: Bool =
@ -107,7 +121,7 @@ extension InputHandler {
return true
case .kSpace where state.type != .ofInputting:
guard !(prefs.useSpaceToCommitHighlightedSCPCCandidate && prefs.useSCPCTypingMode) else {
delegate.candidateSelectionConfirmedByInputHandler(at: ctlCandidate.highlightedIndex)
confirmHighlightedCandidate()
return true
}
let updated: Bool =
@ -140,11 +154,19 @@ extension InputHandler {
}
return true
case .kHome:
if let imkC = imkC, let nsEvent = input as? NSEvent {
imkC.process(event: nsEvent)
return true
}
_ =
(ctlCandidate.highlightedIndex == 0)
? delegate.callError("9B6EDE8D") : (ctlCandidate.highlightedIndex = 0)
return true
case .kEnd:
if let imkC = imkC, let nsEvent = input as? NSEvent {
imkC.process(event: nsEvent)
return true
}
let maxIndex = state.candidates.count - 1
_ =
(ctlCandidate.highlightedIndex == maxIndex)
@ -154,10 +176,27 @@ extension InputHandler {
}
}
// MARK: IMKCandidates
input = {
guard imkC != nil else { return input }
guard let eventToDeal = input as? NSEvent else { return input }
return CtlCandidateIMK.replaceNumPadKeyCodes(target: eventToDeal) ?? eventToDeal
}()
// MARK: (Associated Phrases)
if state.type == .ofAssociates {
if !input.isShiftHold { return false }
if !input.isShiftHold {
return false
}
// input Shift NSEvent IMKCandidates
if let imkC = imkC, let inputEvent = input as? NSEvent,
let inputEventShifted = CtlCandidateIMK.giveSelectionKeySansModifiers(from: inputEvent)
{
imkC.process(event: inputEventShifted)
return true
}
}
var index: Int?
@ -173,9 +212,19 @@ extension InputHandler {
break checkSelectionKey
}
if let index = index, let candidateIndex = ctlCandidate.candidateIndexAtKeyLabelIndex(index) {
delegate.candidateSelectionConfirmedByInputHandler(at: candidateIndex)
return true
//
if let index = index {
if let imkC = imkC, let oldEvent = input as? NSEvent {
if input.isShiftHold, let newEvent = CtlCandidateIMK.giveSelectionKeySansModifiers(from: oldEvent) {
imkC.process(event: newEvent)
} else {
imkC.process(event: oldEvent)
}
return true
} else if let candidateIndex = ctlCandidate.candidateIndexAtKeyLabelIndex(index) {
delegate.candidateSelectionConfirmedByInputHandler(at: candidateIndex)
return true
}
}
if state.type == .ofAssociates { return false }
@ -216,8 +265,7 @@ extension InputHandler {
}
if shouldAutoSelectCandidate {
guard let candidateIndex = ctlCandidate.candidateIndexAtKeyLabelIndex(0) else { return true }
delegate.candidateSelectionConfirmedByInputHandler(at: candidateIndex)
confirmHighlightedCandidate() //
delegate.switchState(IMEState.ofAbortion())
return triageInput(event: input)
}

View File

@ -1,181 +0,0 @@
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
/// 調 NSEvent
import CocoaExtension
import InputMethodKit
import Shared
// MARK: - § 調 (Handle Input with States)
extension InputHandler {
/// IMK
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
public func handleEvent(_ event: NSEvent) -> Bool {
imkCandidatesEventPreHandler(event: event) ?? triageInput(event: event)
}
/// IMK
/// handle()
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
private func imkCandidatesEventPreHandler(event eventToDeal: NSEvent) -> Bool? {
guard prefs.useIMKCandidateWindow else { return nil }
guard let delegate = delegate, delegate.state.isCandidateContainer else { return nil }
// IMK IMK
// interpretKeyEvents()
// - imkCandidates.interpretKeyEvents()
// - delegate SessionCtl InputHandler
if let imkCandidates = delegate.candidateController() as? CtlCandidateIMK, imkCandidates.visible {
let event: NSEvent = CtlCandidateIMK.replaceNumPadKeyCodes(target: eventToDeal) ?? eventToDeal
// Shift+Enter delegate inputHandler
// Shift Flags
if event.isShiftHold, event.isEnter {
guard let newEvent = event.reinitiate(modifierFlags: []) else {
IMEApp.buzz()
return true
}
return imkCandidatesEventSubHandler(event: newEvent)
}
//
if let newChar = CtlCandidateIMK.defaultIMKSelectionKey[event.keyCode],
event.isShiftHold, delegate.state.type == .ofAssociates,
let newEvent = event.reinitiate(modifierFlags: [], characters: newChar)
{
if #available(macOS 10.14, *) {
PrefMgr.shared.failureFlagForIMKCandidates = true
imkCandidates.handleKeyboardEvent(newEvent)
PrefMgr.shared.failureFlagForIMKCandidates = false
} else {
imkCandidates.interpretKeyEvents([newEvent])
}
return true
}
return imkCandidatesEventSubHandler(event: event)
}
return nil
}
private func imkCandidatesEventSubHandler(event: NSEvent) -> Bool {
guard let delegate = delegate else { return false }
let eventArray = [event]
guard let imkC = delegate.candidateController() as? CtlCandidateIMK else { return false }
if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) {
return triageInput(event: event)
} else if event.isSymbolMenuPhysicalKey {
//
switch imkC.currentLayout {
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
} else if event.isSpace {
if prefs.useSpaceToCommitHighlightedSCPCCandidate, prefs.useSCPCTypingMode,
let eventTranslated = event.reinitiate(keyCode: KeyCode.kCarriageReturn.rawValue)
{
if #available(macOS 10.14, *) {
PrefMgr.shared.failureFlagForIMKCandidates = true
imkC.handleKeyboardEvent(eventTranslated)
PrefMgr.shared.failureFlagForIMKCandidates = false
} else {
imkC.interpretKeyEvents([eventTranslated])
}
return true
}
switch prefs.specifyShiftSpaceKeyBehavior {
case true: _ = event.isShiftHold ? imkC.highlightNextCandidate() : imkC.showNextPage()
case false: _ = event.isShiftHold ? imkC.showNextPage() : imkC.highlightNextCandidate()
}
return true
} else if event.isTab {
switch prefs.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 prefs.useSCPCTypingMode, delegate.state.type == .ofAssociates {
// input.isShiftHold delegate.handle()
return event.isShiftHold ? true : triageInput(event: event)
} else {
if #available(macOS 10.14, *) {
PrefMgr.shared.failureFlagForIMKCandidates = true
imkC.handleKeyboardEvent(newEvent)
PrefMgr.shared.failureFlagForIMKCandidates = false
} else {
imkC.interpretKeyEvents([newEvent])
}
return true
}
}
}
// Shift+Command+[] Chrome Ctrl
let ctrlCMD: Bool = event.modifierFlags == [.control, .command]
let ctrlShiftCMD: Bool = event.modifierFlags == [.control, .command, .shift]
if ctrlShiftCMD || ctrlCMD {
// JIS US
let isJIS: Bool = KBGetLayoutType(Int16(LMGetKbdType())) == kKeyboardJIS
switch (event.keyCode, isJIS) {
case (30, true), (33, false):
_ = imkC.highlightPreviousCandidate() ? {}() : delegate.callError("8B144DCD")
return true
case (42, true), (30, false):
_ = imkC.highlightNextCandidate() ? {}() : delegate.callError("D2ABB507")
return true
default: break
}
}
if prefs.useSCPCTypingMode, !event.isReservedKey {
return triageInput(event: event)
}
if delegate.state.type == .ofAssociates,
!event.isPageUp, !event.isPageDown, !event.isCursorForward, !event.isCursorBackward,
!event.isCursorClockLeft, !event.isCursorClockRight, !event.isSpace,
!event.isEnter || !prefs.alsoConfirmAssociatedCandidatesByEnter
{
return triageInput(event: event)
}
imkC.interpretKeyEvents(eventArray)
return true
}
}
}

View File

@ -16,7 +16,7 @@ import Shared
// MARK: - § 調 (Handle Input with States) * Triage
extension InputHandler {
public extension InputHandler {
func triageInput(event input: InputSignalProtocol) -> Bool {
guard let delegate = delegate else { return false }
var state: IMEStateProtocol { delegate.state }

View File

@ -127,15 +127,6 @@ public extension SessionCtl {
}
}()
if #available(macOS 10.14, *) {
// Spotlight IMK
if let ctlCandidateCurrent = candidateUI as? CtlCandidateIMK {
PrefMgr.shared.failureFlagForIMKCandidates = true
ctlCandidateCurrent.setWindowLevel(UInt64(CGShieldingWindowLevel() + 2))
PrefMgr.shared.failureFlagForIMKCandidates = false
}
}
if let ctlCandidateCurrent = candidateUI as? CtlCandidateTDK {
ctlCandidateCurrent.useMouseScrolling = PrefMgr.shared.enableMouseScrollingForTDKCandidatesCocoa
if #available(macOS 10.15, *) {

View File

@ -150,7 +150,7 @@ public extension SessionCtl {
Self.areWeNerfing = eventToDeal.modifierFlags == [.shift, .command]
/// commonEventHandler
let result = inputHandler.handleEvent(eventToDeal)
let result = inputHandler.triageInput(event: eventToDeal)
if !result {
// .ofMarking
if [.ofEmpty].contains(state.type) { tooltipInstance.hide() }

View File

@ -45,9 +45,7 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
public var candidateFont = NSFont.systemFont(ofSize: 16) {
didSet {
if #available(macOS 10.14, *) {
PrefMgr.shared.failureFlagForIMKCandidates = true
setFontSize(candidateFont.pointSize)
PrefMgr.shared.failureFlagForIMKCandidates = false
protectedCall { self.setFontSize(self.candidateFont.pointSize) }
}
var attributes = attributes()
// FB11300759: Set "NSAttributedString.Key.font" doesn't work.
@ -97,6 +95,14 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
fatalError("init(coder:) has not been implemented")
}
private func protectedCall(_ task: @escaping () -> Void) {
guard #available(macOS 10.14, *) else { return }
let key = UserDef.kFailureFlagForIMKCandidates.rawValue
UserDefaults.standard.set(true, forKey: key)
task()
UserDefaults.standard.set(false, forKey: key)
}
public func reloadData() {
// guard let delegate = delegate else { return } //
//
@ -105,18 +111,15 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
update()
}
/// IMKCandidates
/// IMK inputHandler `SessionCtl_HandleEvent`
// IMK
@discardableResult public func showNextPage() -> Bool {
do { currentLayout == .vertical ? moveRight(self) : moveDown(self) }
scrollPageDown(self)
return true
}
// IMK
@discardableResult public func showPreviousPage() -> Bool {
do { currentLayout == .vertical ? moveLeft(self) : moveUp(self) }
scrollPageUp(self)
return true
}
@ -155,6 +158,24 @@ public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol {
}
set { selectCandidate(withIdentifier: newValue) }
}
@discardableResult public func process(event theEvent: NSEvent) -> Bool {
guard #available(macOS 10.14, *) else {
interpretKeyEvents([theEvent])
return true
}
var result = true
protectedCall { result = self.handleKeyboardEvent(theEvent) }
return result
}
override public func update() {
super.update()
guard #available(macOS 10.14, *) else { return }
// Spotlight macOS 10.14 IMK
let level = UInt64(CGShieldingWindowLevel() + 2)
protectedCall { self.setWindowLevel(level) }
}
}
// MARK: - Generate TISInputSource Object
@ -180,6 +201,14 @@ var currentTISInputSource: TISInputSource? {
// MARK: - Translating NumPad KeyCodes to Default IMK Candidate Selection KeyCodes.
public extension CtlCandidateIMK {
static func giveSelectionKeySansModifiers(from event: NSEvent) -> NSEvent? {
let mapDefaultIMKSelectionKey: [UInt16: String] = [
18: "1", 19: "2", 20: "3", 21: "4", 23: "5", 22: "6", 26: "7", 28: "8", 25: "9",
]
guard let newChar = mapDefaultIMKSelectionKey[event.keyCode] else { return nil }
return event.reinitiate(modifierFlags: [], characters: newChar)
}
static func replaceNumPadKeyCodes(target event: NSEvent) -> NSEvent? {
let mapNumPadKeyCodeTranslation: [UInt16: UInt16] = [
83: 18, 84: 19, 85: 20, 86: 21, 87: 23, 88: 22, 89: 26, 91: 28, 92: 25,

View File

@ -96,7 +96,6 @@
5BDB7A4128D4824A001AC277 /* Megrez in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A4028D4824A001AC277 /* Megrez */; };
5BDB7A4528D4824A001AC277 /* ShiftKeyUpChecker in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A4428D4824A001AC277 /* ShiftKeyUpChecker */; };
5BDB7A4728D4824A001AC277 /* Tekkon in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A4628D4824A001AC277 /* Tekkon */; };
5BE1F8A928F86AB5006C7FF5 /* InputHandler_HandleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BE1F8A828F86AB5006C7FF5 /* InputHandler_HandleEvent.swift */; };
5BE377A0288FED8D0037365B /* InputHandler_HandleComposition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BE3779F288FED8D0037365B /* InputHandler_HandleComposition.swift */; };
5BEDB721283B4C250078EB25 /* data-cns.json in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71D283B4AEA0078EB25 /* data-cns.json */; };
5BEDB722283B4C250078EB25 /* data-zhuyinwen.json in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.json */; };
@ -298,7 +297,6 @@
5BDCBB4827B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
5BDCBB4927B4F6C700D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
5BDCBB4A27B4F6C700D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
5BE1F8A828F86AB5006C7FF5 /* InputHandler_HandleEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputHandler_HandleEvent.swift; sourceTree = "<group>"; };
5BE3779F288FED8D0037365B /* InputHandler_HandleComposition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputHandler_HandleComposition.swift; sourceTree = "<group>"; };
5BE8A8C4281EE65300197741 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = "<group>"; };
5BEDB71C283B4AEA0078EB25 /* data-chs.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "data-chs.json"; path = "Data/data-chs.json"; sourceTree = "<group>"; };
@ -693,7 +691,6 @@
5BD0113C2818543900609769 /* InputHandler_Core.swift */,
5B782EC3280C243C007276DE /* InputHandler_HandleCandidate.swift */,
5BE3779F288FED8D0037365B /* InputHandler_HandleComposition.swift */,
5BE1F8A828F86AB5006C7FF5 /* InputHandler_HandleEvent.swift */,
5B3133BE280B229700A4A505 /* InputHandler_HandleStates.swift */,
5B7F225C2808501000DDD3CB /* InputHandler_TriageInput.swift */,
5BAEFACF28012565001F42C9 /* LMMgr_Core.swift */,
@ -1128,7 +1125,6 @@
5BB1D7F42999027200EA8D2C /* PrefUITabs.swift in Sources */,
5B33844F29B8B4C200FCB497 /* LMMgr_PhraseEditorDelegate.swift in Sources */,
5B21176C287539BB000443A9 /* SessionCtl_HandleStates.swift in Sources */,
5BE1F8A928F86AB5006C7FF5 /* InputHandler_HandleEvent.swift in Sources */,
5B69938C293B811F0057CB8E /* VwrPrefPanePhrases.swift in Sources */,
5BAEFAD028012565001F42C9 /* LMMgr_Core.swift in Sources */,
5BCC631629407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift in Sources */,