Repo // Stop previous session from interfering current palettes.
This commit is contained in:
parent
1c92ab8edf
commit
73b0da3eb4
|
@ -30,7 +30,13 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate {
|
||||||
public var useMouseScrolling: Bool = true
|
public var useMouseScrolling: Bool = true
|
||||||
private static var thePool: CandidatePool = .init(candidates: [])
|
private static var thePool: CandidatePool = .init(candidates: [])
|
||||||
private static var currentView: NSView = .init()
|
private static var currentView: NSView = .init()
|
||||||
public static var currentMenu: NSMenu?
|
|
||||||
|
public static var currentMenu: NSMenu? {
|
||||||
|
willSet {
|
||||||
|
currentMenu?.cancelTracking()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static var currentWindow: NSWindow? {
|
public static var currentWindow: NSWindow? {
|
||||||
willSet {
|
willSet {
|
||||||
currentWindow?.orderOut(nil)
|
currentWindow?.orderOut(nil)
|
||||||
|
|
|
@ -46,16 +46,6 @@ public class SessionCtl: IMKInputController {
|
||||||
/// 用來標記當前副本是否已處於活動狀態。
|
/// 用來標記當前副本是否已處於活動狀態。
|
||||||
public var isActivated = false
|
public var isActivated = false
|
||||||
|
|
||||||
/// 用来記錄當前副本是否處於開機階段(activateServer 執行後 0.1 秒以內都算)。
|
|
||||||
public private(set) var isBootingUp: Bool = true {
|
|
||||||
didSet {
|
|
||||||
guard isBootingUp else { return }
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
||||||
self.isBootingUp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 當前副本的客體是否是輸入法本體?
|
/// 當前副本的客體是否是輸入法本體?
|
||||||
public var isServingIMEItself: Bool = false
|
public var isServingIMEItself: Bool = false
|
||||||
|
|
||||||
|
@ -219,22 +209,12 @@ public class SessionCtl: IMKInputController {
|
||||||
|
|
||||||
/// 所有建構子都會執行的共用部分,在 super.init() 之後執行。
|
/// 所有建構子都會執行的共用部分,在 super.init() 之後執行。
|
||||||
private func construct(client theClient: (IMKTextInput & NSObjectProtocol)? = nil) {
|
private func construct(client theClient: (IMKTextInput & NSObjectProtocol)? = nil) {
|
||||||
DispatchQueue.main.async { [weak self] in
|
activate(server: theClient ?? client())
|
||||||
guard let self = self else { return }
|
// defer 會觸發 didSet,所以不用擔心。
|
||||||
// 關掉所有之前的副本的視窗。
|
defer {
|
||||||
Self.current?.hidePalettes()
|
inputMode = .init(rawValue: PrefMgr.shared.mostRecentInputMode) ?? .imeModeNULL
|
||||||
Self.current = self
|
|
||||||
self.inputHandler = InputHandler(
|
|
||||||
lm: LMMgr.currentLM, uom: LMMgr.currentUOM, pref: PrefMgr.shared
|
|
||||||
)
|
|
||||||
self.inputHandler?.delegate = self
|
|
||||||
self.syncBaseLMPrefs()
|
|
||||||
// 下述兩行很有必要,否則輸入法會在手動重啟之後無法立刻生效。
|
|
||||||
let maybeClient = theClient ?? self.client()
|
|
||||||
self.activateServer(maybeClient)
|
|
||||||
// GCD 會觸發 didSet,所以不用擔心。
|
|
||||||
self.inputMode = .init(rawValue: PrefMgr.shared.mostRecentInputMode) ?? .imeModeNULL
|
|
||||||
}
|
}
|
||||||
|
vCLog("constuct() executed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,10 +223,9 @@ public class SessionCtl: IMKInputController {
|
||||||
public extension SessionCtl {
|
public extension SessionCtl {
|
||||||
/// 強制重設當前鍵盤佈局、使其與偏好設定同步。
|
/// 強制重設當前鍵盤佈局、使其與偏好設定同步。
|
||||||
func setKeyLayout() {
|
func setKeyLayout() {
|
||||||
guard let client = client(), !isServingIMEItself else { return }
|
|
||||||
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
guard let client = self.client(), !self.isServingIMEItself else { return }
|
||||||
if self.isASCIIMode, IMKHelper.isDynamicBasicKeyboardLayoutEnabled {
|
if self.isASCIIMode, IMKHelper.isDynamicBasicKeyboardLayoutEnabled {
|
||||||
client.overrideKeyboard(withKeyboardNamed: PrefMgr.shared.alphanumericalKeyboardLayout)
|
client.overrideKeyboard(withKeyboardNamed: PrefMgr.shared.alphanumericalKeyboardLayout)
|
||||||
return
|
return
|
||||||
|
@ -282,14 +261,20 @@ public extension SessionCtl {
|
||||||
/// 啟用輸入法時,會觸發該函式。
|
/// 啟用輸入法時,會觸發該函式。
|
||||||
/// - Parameter sender: 呼叫了該函式的客體。
|
/// - Parameter sender: 呼叫了該函式的客體。
|
||||||
override func activateServer(_ sender: Any!) {
|
override func activateServer(_ sender: Any!) {
|
||||||
|
activate(server: sender as? IMKTextInput ?? client())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 啟用輸入法時,會觸發該函式。
|
||||||
|
/// - Parameter sender: 呼叫了該函式的客體。
|
||||||
|
func activate(server sender: IMKTextInput) {
|
||||||
|
// 關掉所有之前的副本的視窗。
|
||||||
|
Self.current?.hidePalettes()
|
||||||
|
Self.current = self
|
||||||
super.activateServer(sender)
|
super.activateServer(sender)
|
||||||
isBootingUp = true
|
if let senderBundleID: String = sender.bundleIdentifier() {
|
||||||
DispatchQueue.main.async { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
if let senderBundleID: String = (sender as? IMKTextInput)?.bundleIdentifier() {
|
|
||||||
vCLog("activateServer(\(senderBundleID))")
|
vCLog("activateServer(\(senderBundleID))")
|
||||||
self.isServingIMEItself = Bundle.main.bundleIdentifier == senderBundleID
|
isServingIMEItself = Bundle.main.bundleIdentifier == senderBundleID
|
||||||
self.clientBundleIdentifier = senderBundleID
|
clientBundleIdentifier = senderBundleID
|
||||||
// 只要使用者沒有勾選檢查更新、沒有主動做出要檢查更新的操作,就不要檢查更新。
|
// 只要使用者沒有勾選檢查更新、沒有主動做出要檢查更新的操作,就不要檢查更新。
|
||||||
if PrefMgr.shared.checkUpdateAutomatically {
|
if PrefMgr.shared.checkUpdateAutomatically {
|
||||||
AppDelegate.shared.checkUpdate(forced: false) {
|
AppDelegate.shared.checkUpdate(forced: false) {
|
||||||
|
@ -297,50 +282,41 @@ public extension SessionCtl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
// 自動啟用肛塞(廉恥模式),除非這一天是愚人節。
|
// 自動啟用肛塞(廉恥模式),除非這一天是愚人節。
|
||||||
if !Date.isTodayTheDate(from: 0401), !PrefMgr.shared.shouldNotFartInLieuOfBeep {
|
if !Date.isTodayTheDate(from: 0401), !PrefMgr.shared.shouldNotFartInLieuOfBeep {
|
||||||
PrefMgr.shared.shouldNotFartInLieuOfBeep = true
|
PrefMgr.shared.shouldNotFartInLieuOfBeep = true
|
||||||
}
|
}
|
||||||
|
if inputMode != IMEApp.currentInputMode {
|
||||||
|
inputMode = IMEApp.currentInputMode
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
if self.inputMode != IMEApp.currentInputMode {
|
|
||||||
self.inputMode = IMEApp.currentInputMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
// 清理掉上一個會話的選字窗及其選單。
|
// 清理掉上一個會話的選字窗及其選單。
|
||||||
if self.candidateUI is CtlCandidateTDK {
|
if candidateUI is CtlCandidateTDK {
|
||||||
self.candidateUI = nil
|
candidateUI = nil
|
||||||
}
|
}
|
||||||
CtlCandidateTDK.currentMenu?.cancelTracking()
|
|
||||||
CtlCandidateTDK.currentMenu = nil
|
CtlCandidateTDK.currentMenu = nil
|
||||||
CtlCandidateTDK.currentWindow?.orderOut(nil)
|
|
||||||
CtlCandidateTDK.currentWindow = nil
|
CtlCandidateTDK.currentWindow = nil
|
||||||
}
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
// MARK: 正式過程
|
||||||
guard let self = self else { return }
|
|
||||||
if self.isActivated { return }
|
if isActivated { return }
|
||||||
|
|
||||||
// 這裡不需要 setValue(),因為 IMK 會在自動呼叫 activateServer() 之後自動執行 setValue()。
|
// 這裡不需要 setValue(),因為 IMK 會在自動呼叫 activateServer() 之後自動執行 setValue()。
|
||||||
self.inputHandler = InputHandler(
|
inputHandler = InputHandler(
|
||||||
lm: LMMgr.currentLM, uom: LMMgr.currentUOM, pref: PrefMgr.shared
|
lm: LMMgr.currentLM, uom: LMMgr.currentUOM, pref: PrefMgr.shared
|
||||||
)
|
)
|
||||||
self.inputHandler?.delegate = self
|
inputHandler?.delegate = self
|
||||||
self.syncBaseLMPrefs()
|
syncBaseLMPrefs()
|
||||||
|
|
||||||
Self.theShiftKeyDetector.toggleWithLShift = PrefMgr.shared.togglingAlphanumericalModeWithLShift
|
Self.theShiftKeyDetector.toggleWithLShift = PrefMgr.shared.togglingAlphanumericalModeWithLShift
|
||||||
Self.theShiftKeyDetector.toggleWithRShift = PrefMgr.shared.togglingAlphanumericalModeWithRShift
|
Self.theShiftKeyDetector.toggleWithRShift = PrefMgr.shared.togglingAlphanumericalModeWithRShift
|
||||||
|
|
||||||
if self.isASCIIMode, !IMEApp.isKeyboardJIS {
|
if isASCIIMode, !IMEApp.isKeyboardJIS {
|
||||||
if #available(macOS 10.15, *) {
|
if #available(macOS 10.15, *) {
|
||||||
if !Self.theShiftKeyDetector.enabled {
|
if !Self.theShiftKeyDetector.enabled {
|
||||||
self.isASCIIMode = false
|
self.isASCIIMode = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.isASCIIMode = false
|
isASCIIMode = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,10 +324,9 @@ public extension SessionCtl {
|
||||||
AppDelegate.shared.checkMemoryUsage()
|
AppDelegate.shared.checkMemoryUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state = IMEState.ofEmpty()
|
state = IMEState.ofEmpty()
|
||||||
self.isActivated = true // 登記啟用狀態。
|
isActivated = true // 登記啟用狀態。
|
||||||
self.setKeyLayout()
|
setKeyLayout()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 停用輸入法時,會觸發該函式。
|
/// 停用輸入法時,會觸發該函式。
|
||||||
|
|
|
@ -46,7 +46,7 @@ public extension SessionCtl {
|
||||||
// 這裡移除一些處理,轉而交給 commitComposition() 代為執行。
|
// 這裡移除一些處理,轉而交給 commitComposition() 代為執行。
|
||||||
// 這裡不需要 clearInlineDisplay() ,否則會觸發無限迴圈。
|
// 這裡不需要 clearInlineDisplay() ,否則會觸發無限迴圈。
|
||||||
// 對於 IMK 選字窗的顯示狀態糾正的行為交給 inputMode.didSet() 來處理。
|
// 對於 IMK 選字窗的顯示狀態糾正的行為交給 inputMode.didSet() 來處理。
|
||||||
hidePalettes()
|
// 此處的 hidePalettes() 僅適合由新的 Session 來呼叫,否則可能會干擾到新的 Session。
|
||||||
inputHandler?.clear()
|
inputHandler?.clear()
|
||||||
if ![.ofAbortion, .ofEmpty].contains(previous.type), !previous.displayedText.isEmpty {
|
if ![.ofAbortion, .ofEmpty].contains(previous.type), !previous.displayedText.isEmpty {
|
||||||
clearInlineDisplay()
|
clearInlineDisplay()
|
||||||
|
|
Loading…
Reference in New Issue