SessionCtl // ctlCandidateCurrent -> candidateUI.
This commit is contained in:
parent
06e984b6f9
commit
0b2a046885
|
@ -29,7 +29,7 @@ public class SessionCtl: IMKInputController {
|
||||||
public static var areWeNerfing = false
|
public static var areWeNerfing = false
|
||||||
|
|
||||||
/// 目前在用的的選字窗副本。
|
/// 目前在用的的選字窗副本。
|
||||||
public var ctlCandidateCurrent: CtlCandidateProtocol = {
|
public var candidateUI: CtlCandidateProtocol = {
|
||||||
let direction: NSUserInterfaceLayoutOrientation =
|
let direction: NSUserInterfaceLayoutOrientation =
|
||||||
PrefMgr.shared.useHorizontalCandidateList ? .horizontal : .vertical
|
PrefMgr.shared.useHorizontalCandidateList ? .horizontal : .vertical
|
||||||
if #available(macOS 10.15, *) {
|
if #available(macOS 10.15, *) {
|
||||||
|
@ -135,7 +135,7 @@ public class SessionCtl: IMKInputController {
|
||||||
// 雖然所有在這個函式內影響到的變數都改為動態變數了(不會出現跨副本波及的情況),
|
// 雖然所有在這個函式內影響到的變數都改為動態變數了(不會出現跨副本波及的情況),
|
||||||
// 但 IMKCandidates 是有內部共用副本的、會被波及。所以在這裡糾偏一下。
|
// 但 IMKCandidates 是有內部共用副本的、會被波及。所以在這裡糾偏一下。
|
||||||
if PrefMgr.shared.useIMKCandidateWindow {
|
if PrefMgr.shared.useIMKCandidateWindow {
|
||||||
guard let imkC = ctlCandidateCurrent as? CtlCandidateIMK else { return }
|
guard let imkC = candidateUI as? CtlCandidateIMK else { return }
|
||||||
if state.isCandidateContainer, !imkC.visible {
|
if state.isCandidateContainer, !imkC.visible {
|
||||||
handle(state: state, replace: false)
|
handle(state: state, replace: false)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,8 @@ extension SessionCtl {
|
||||||
|
|
||||||
// 因為偶爾會收到與 activateServer 有關的以「強制拆 nil」為理由的報錯,
|
// 因為偶爾會收到與 activateServer 有關的以「強制拆 nil」為理由的報錯,
|
||||||
// 所以這裡添加這句、來試圖應對這種情況。
|
// 所以這裡添加這句、來試圖應對這種情況。
|
||||||
if inputHandler.delegate == nil { inputHandler.delegate = self }
|
inputHandler.delegate = self
|
||||||
|
candidateUI.delegate = self
|
||||||
// 這裡不需要 setValue(),因為 IMK 會在自動呼叫 activateServer() 之後自動執行 setValue()。
|
// 這裡不需要 setValue(),因為 IMK 會在自動呼叫 activateServer() 之後自動執行 setValue()。
|
||||||
inputHandler.clear() // 這句不要砍,因為後面 handle State.Empty() 不一定執行。
|
inputHandler.clear() // 這句不要砍,因為後面 handle State.Empty() 不一定執行。
|
||||||
inputHandler.ensureKeyboardParser()
|
inputHandler.ensureKeyboardParser()
|
||||||
|
|
|
@ -16,7 +16,7 @@ extension SessionCtl: InputHandlerDelegate {
|
||||||
return client.bundleIdentifier() ?? ""
|
return client.bundleIdentifier() ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
public func candidateController() -> CtlCandidateProtocol { ctlCandidateCurrent }
|
public func candidateController() -> CtlCandidateProtocol { candidateUI }
|
||||||
|
|
||||||
public func candidateSelectionCalledByInputHandler(at index: Int) {
|
public func candidateSelectionCalledByInputHandler(at index: Int) {
|
||||||
candidatePairSelected(at: index)
|
candidatePairSelected(at: index)
|
||||||
|
|
|
@ -82,35 +82,35 @@ extension SessionCtl {
|
||||||
: .horizontal)
|
: .horizontal)
|
||||||
|
|
||||||
/// 先取消既有的選字窗的內容顯示。否則可能會重複生成選字窗的 NSWindow()。
|
/// 先取消既有的選字窗的內容顯示。否則可能會重複生成選字窗的 NSWindow()。
|
||||||
ctlCandidateCurrent.visible = false
|
candidateUI.visible = false
|
||||||
/// 然後再重新初期化。
|
/// 然後再重新初期化。
|
||||||
if #available(macOS 10.15, *) {
|
if #available(macOS 10.15, *) {
|
||||||
ctlCandidateCurrent =
|
candidateUI =
|
||||||
PrefMgr.shared.useIMKCandidateWindow
|
PrefMgr.shared.useIMKCandidateWindow
|
||||||
? CtlCandidateIMK(candidateLayout) : CtlCandidateTDK(candidateLayout)
|
? CtlCandidateIMK(candidateLayout) : CtlCandidateTDK(candidateLayout)
|
||||||
if let candidateTDK = ctlCandidateCurrent as? CtlCandidateTDK {
|
if let candidateTDK = candidateUI as? CtlCandidateTDK {
|
||||||
candidateTDK.maxLinesPerPage = isVerticalTyping ? 1 : 3
|
candidateTDK.maxLinesPerPage = isVerticalTyping ? 1 : 3
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctlCandidateCurrent = CtlCandidateIMK(candidateLayout)
|
candidateUI = CtlCandidateIMK(candidateLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctlCandidateCurrent.candidateFont = Self.candidateFont(
|
candidateUI.candidateFont = Self.candidateFont(
|
||||||
name: PrefMgr.shared.candidateTextFontName, size: PrefMgr.shared.candidateListTextSize
|
name: PrefMgr.shared.candidateTextFontName, size: PrefMgr.shared.candidateListTextSize
|
||||||
)
|
)
|
||||||
|
|
||||||
if PrefMgr.shared.cassetteEnabled {
|
if PrefMgr.shared.cassetteEnabled {
|
||||||
ctlCandidateCurrent.tooltip =
|
candidateUI.tooltip =
|
||||||
isVerticalTyping ? "📼" : "📼 " + NSLocalizedString("CIN Cassette Mode", comment: "")
|
isVerticalTyping ? "📼" : "📼 " + NSLocalizedString("CIN Cassette Mode", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.type == .ofAssociates {
|
if state.type == .ofAssociates {
|
||||||
ctlCandidateCurrent.tooltip =
|
candidateUI.tooltip =
|
||||||
isVerticalTyping ? "⇧" : NSLocalizedString("Hold ⇧ to choose associates.", comment: "")
|
isVerticalTyping ? "⇧" : NSLocalizedString("Hold ⇧ to choose associates.", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctlCandidateCurrent.useLangIdentifier = PrefMgr.shared.handleDefaultCandidateFontsByLangIdentifier
|
candidateUI.useLangIdentifier = PrefMgr.shared.handleDefaultCandidateFontsByLangIdentifier
|
||||||
ctlCandidateCurrent.locale = {
|
candidateUI.locale = {
|
||||||
switch inputMode {
|
switch inputMode {
|
||||||
case .imeModeCHS: return "zh-Hans"
|
case .imeModeCHS: return "zh-Hans"
|
||||||
case .imeModeCHT:
|
case .imeModeCHT:
|
||||||
|
@ -124,18 +124,18 @@ extension SessionCtl {
|
||||||
|
|
||||||
if #available(macOS 10.14, *) {
|
if #available(macOS 10.14, *) {
|
||||||
// Spotlight 視窗會擋住 IMK 選字窗,所以需要特殊處理。
|
// Spotlight 視窗會擋住 IMK 選字窗,所以需要特殊處理。
|
||||||
if let ctlCandidateCurrent = ctlCandidateCurrent as? CtlCandidateIMK {
|
if let ctlCandidateCurrent = candidateUI as? CtlCandidateIMK {
|
||||||
while ctlCandidateCurrent.windowLevel() <= client.windowLevel() {
|
while ctlCandidateCurrent.windowLevel() <= client.windowLevel() {
|
||||||
ctlCandidateCurrent.setWindowLevel(UInt64(max(0, client.windowLevel() + 1000)))
|
ctlCandidateCurrent.setWindowLevel(UInt64(max(0, client.windowLevel() + 1000)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctlCandidateCurrent.delegate = self // 會自動觸發田所選字窗的資料重載。
|
candidateUI.delegate = self // 會自動觸發田所選字窗的資料重載。
|
||||||
ctlCandidateCurrent.visible = true
|
candidateUI.visible = true
|
||||||
|
|
||||||
if isVerticalTyping {
|
if isVerticalTyping {
|
||||||
ctlCandidateCurrent.set(
|
candidateUI.set(
|
||||||
windowTopLeftPoint: NSPoint(
|
windowTopLeftPoint: NSPoint(
|
||||||
x: lineHeightRect().origin.x + lineHeightRect().size.width + 4.0, y: lineHeightRect().origin.y - 4.0
|
x: lineHeightRect().origin.x + lineHeightRect().size.width + 4.0, y: lineHeightRect().origin.y - 4.0
|
||||||
),
|
),
|
||||||
|
@ -143,7 +143,7 @@ extension SessionCtl {
|
||||||
useGCD: true
|
useGCD: true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ctlCandidateCurrent.set(
|
candidateUI.set(
|
||||||
windowTopLeftPoint: NSPoint(x: lineHeightRect().origin.x, y: lineHeightRect().origin.y - 4.0),
|
windowTopLeftPoint: NSPoint(x: lineHeightRect().origin.x, y: lineHeightRect().origin.y - 4.0),
|
||||||
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0,
|
bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0,
|
||||||
useGCD: true
|
useGCD: true
|
||||||
|
|
|
@ -45,7 +45,7 @@ extension SessionCtl {
|
||||||
// 這裡移除一些處理,轉而交給 commitComposition() 代為執行。
|
// 這裡移除一些處理,轉而交給 commitComposition() 代為執行。
|
||||||
// 這裡不需要 clearInlineDisplay() ,否則會觸發無限迴圈。
|
// 這裡不需要 clearInlineDisplay() ,否則會觸發無限迴圈。
|
||||||
// 對於 IMK 選字窗的顯示狀態糾正的行為交給 inputMode.didSet() 來處理。
|
// 對於 IMK 選字窗的顯示狀態糾正的行為交給 inputMode.didSet() 來處理。
|
||||||
ctlCandidateCurrent.visible = false
|
candidateUI.visible = false
|
||||||
popupCompositionBuffer.hide()
|
popupCompositionBuffer.hide()
|
||||||
tooltipInstance.hide()
|
tooltipInstance.hide()
|
||||||
case .ofEmpty, .ofAbortion, .ofCommitting:
|
case .ofEmpty, .ofAbortion, .ofCommitting:
|
||||||
|
@ -58,22 +58,21 @@ extension SessionCtl {
|
||||||
if replace { state = IMEState.ofEmpty() }
|
if replace { state = IMEState.ofEmpty() }
|
||||||
default: break innerCircle
|
default: break innerCircle
|
||||||
}
|
}
|
||||||
ctlCandidateCurrent.visible = false
|
candidateUI.visible = false
|
||||||
// 全專案用以判斷「.Abortion」的地方僅此一處。
|
// 全專案用以判斷「.Abortion」的地方僅此一處。
|
||||||
if previous.hasComposition, ![.ofAbortion, .ofCommitting].contains(newState.type) {
|
if previous.hasComposition, ![.ofAbortion, .ofCommitting].contains(newState.type) {
|
||||||
commit(text: previous.displayedText)
|
commit(text: previous.displayedText)
|
||||||
}
|
}
|
||||||
showTooltip(newState.tooltip, duration: 1) // 會在工具提示為空的時候自動消除顯示。
|
showTooltip(newState.tooltip, duration: 1) // 會在工具提示為空的時候自動消除顯示。
|
||||||
clearInlineDisplay()
|
clearInlineDisplay()
|
||||||
// 最後一道保險
|
|
||||||
inputHandler.clear()
|
inputHandler.clear()
|
||||||
case .ofInputting:
|
case .ofInputting:
|
||||||
ctlCandidateCurrent.visible = false
|
candidateUI.visible = false
|
||||||
commit(text: newState.textToCommit)
|
commit(text: newState.textToCommit)
|
||||||
setInlineDisplayWithCursor()
|
setInlineDisplayWithCursor()
|
||||||
showTooltip(newState.tooltip, duration: 1) // 會在工具提示為空的時候自動消除顯示。
|
showTooltip(newState.tooltip, duration: 1) // 會在工具提示為空的時候自動消除顯示。
|
||||||
case .ofMarking:
|
case .ofMarking:
|
||||||
ctlCandidateCurrent.visible = false
|
candidateUI.visible = false
|
||||||
setInlineDisplayWithCursor()
|
setInlineDisplayWithCursor()
|
||||||
showTooltip(newState.tooltip)
|
showTooltip(newState.tooltip)
|
||||||
case .ofCandidates, .ofAssociates, .ofSymbolTable:
|
case .ofCandidates, .ofAssociates, .ofSymbolTable:
|
||||||
|
|
|
@ -62,8 +62,8 @@ extension SessionCtl {
|
||||||
let annotation = reverseLookup(for: currentCandidate).joined(separator: "\n")
|
let annotation = reverseLookup(for: currentCandidate).joined(separator: "\n")
|
||||||
guard !annotation.isEmpty else { return }
|
guard !annotation.isEmpty else { return }
|
||||||
vCLog("Current Annotation: \(annotation)")
|
vCLog("Current Annotation: \(annotation)")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async { [self] in
|
||||||
guard let imkCandidates = self.ctlCandidateCurrent as? CtlCandidateIMK else { return }
|
guard let imkCandidates = candidateUI as? CtlCandidateIMK else { return }
|
||||||
imkCandidates.showAnnotation(.init(string: annotation))
|
imkCandidates.showAnnotation(.init(string: annotation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue