diff --git a/Source/Modules/SessionCtl_Core.swift b/Source/Modules/SessionCtl_Core.swift index 4274c231..ef4ba745 100644 --- a/Source/Modules/SessionCtl_Core.swift +++ b/Source/Modules/SessionCtl_Core.swift @@ -24,6 +24,8 @@ import TooltipUI /// 輸入會話創建一個控制器型別。因此,對於每個輸入會話,都有一個對應的 IMKInputController。 @objc(SessionCtl) // 必須加上 ObjC,因為 IMK 是用 ObjC 寫的。 public class SessionCtl: IMKInputController { + public static var allInstances: Set = .init() + /// 標記狀態來聲明目前新增的詞彙是否需要賦以非常低的權重。 public static var areWeNerfing = false @@ -197,6 +199,7 @@ extension SessionCtl { } handle(state: IMEState.ofEmpty()) + Self.allInstances.insert(self) } /// 停用輸入法時,會觸發該函式。 @@ -205,6 +208,7 @@ extension SessionCtl { _ = sender // 防止格式整理工具毀掉與此對應的參數。 resetKeyHandler() // 這條會自動搞定 Empty 狀態。 handle(state: IMEState.ofDeactivated()) + Self.allInstances.remove(self) } /// 切換至某一個輸入法的某個副本時(比如威注音的簡體輸入法副本與繁體輸入法副本),會觸發該函式。 diff --git a/Source/Modules/SessionCtl_HandleStates.swift b/Source/Modules/SessionCtl_HandleStates.swift index 289cfc3a..3b6a834a 100644 --- a/Source/Modules/SessionCtl_HandleStates.swift +++ b/Source/Modules/SessionCtl_HandleStates.swift @@ -35,6 +35,18 @@ extension SessionCtl { clearInlineDisplay() // 最後一道保險 keyHandler.clear() + // 特殊處理:deactivateServer() 可能會遲於另一個客體會話的 activateServer() 執行。 + // 雖然所有在這個函式內影響到的變數都改為動態變數了(不會出現跨副本波及的情況), + // 但 IMKCandidates 是有內部共用副本的、會被波及。 + // 所以在這裡糾偏一下、讓所有開啟了選字窗的會話重新顯示選字窗。 + if PrefMgr.shared.useIMKCandidateWindow { + for instance in Self.allInstances { + guard let imkC = instance.ctlCandidateCurrent as? CtlCandidateIMK else { continue } + if instance.state.isCandidateContainer, !imkC.visible { + instance.handle(state: instance.state) + } + } + } case .ofEmpty, .ofAbortion: var previous = previous if state.type == .ofAbortion { @@ -48,7 +60,6 @@ extension SessionCtl { commit(text: previous.displayedText) } // 在這裡手動再取消一次選字窗與工具提示的顯示,可謂雙重保險。 - ctlCandidateCurrent.visible = false tooltipInstance.hide() clearInlineDisplay() // 最後一道保險