From b45d475ede631f9d3ed57a554f4182802b27bd1f Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Sat, 11 Nov 2023 22:29:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E6=A0=8F=E7=9A=84=E4=B8=AD=E8=8B=B1=E6=96=87=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=8C=89=E9=92=AE=E4=BD=8D=E7=BD=AE=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E4=BF=9D=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire.xcodeproj/project.pbxproj | 4 ++ Fire/StatusBar.swift | 2 +- Fire/StatusBarController.swift | 71 ++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Fire/StatusBarController.swift diff --git a/Fire.xcodeproj/project.pbxproj b/Fire.xcodeproj/project.pbxproj index 32f2376..051b19b 100644 --- a/Fire.xcodeproj/project.pbxproj +++ b/Fire.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 67C9A0542AB53F79000B5281 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 67C9A0532AB53F79000B5281 /* Sparkle */; }; 67C9A0582AB5429B000B5281 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 67C9A0562AB5429B000B5281 /* sqlite3.c */; }; 67C9A05B2AB5445E000B5281 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67C9A05A2AB5445E000B5281 /* Security.framework */; }; + 67F0B0D32AFFC282006F835D /* StatusBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67F0B0D22AFFC282006F835D /* StatusBarController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -116,6 +117,7 @@ 67C9A0562AB5429B000B5281 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; 67C9A0572AB5429B000B5281 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite3.h; sourceTree = ""; }; 67C9A05A2AB5445E000B5281 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 67F0B0D22AFFC282006F835D /* StatusBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -203,6 +205,7 @@ 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */, 67C9A0022AB53E83000B5281 /* InputSource.swift */, 67C9A0012AB53E83000B5281 /* MainMenu.xib */, + 67F0B0D22AFFC282006F835D /* StatusBarController.swift */, 67C9A0042AB53E83000B5281 /* StatusBar.swift */, 67C9A0082AB53E83000B5281 /* types.swift */, 67C9A0032AB53E83000B5281 /* Utils.swift */, @@ -433,6 +436,7 @@ 67C9A03C2AB53ED3000B5281 /* StatisticsPane.swift in Sources */, 67C9A0322AB53ED3000B5281 /* CandidatesView.swift in Sources */, 67C9A00B2AB53E83000B5281 /* Utils.swift in Sources */, + 67F0B0D32AFFC282006F835D /* StatusBarController.swift in Sources */, 67C9A0402AB53ED3000B5281 /* ApplicationPane.swift in Sources */, 67C9A0132AB53EB0000B5281 /* build.swift in Sources */, 67C9A0422AB53ED3000B5281 /* ThesaurusPane.swift in Sources */, diff --git a/Fire/StatusBar.swift b/Fire/StatusBar.swift index 954409f..cfb9408 100644 --- a/Fire/StatusBar.swift +++ b/Fire/StatusBar.swift @@ -19,7 +19,7 @@ class StatusBar { private var showInputModeStatusSubscript: AnyCancellable? private init() { // 输入法变化时,根据当前选中状态切换显示 - statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + statusItem = StatusBarController.system.statusItem(autosaveName: "status-indicator", width: NSStatusItem.variableLength) statusItem.button?.title = "中" statusItem.button?.action = #selector(changeInputMode) statusItem.button?.target = self diff --git a/Fire/StatusBarController.swift b/Fire/StatusBarController.swift new file mode 100644 index 0000000..ce9b60c --- /dev/null +++ b/Fire/StatusBarController.swift @@ -0,0 +1,71 @@ +// +// StatusItemController.swift +// Battery Thing +// +// Created by Curtis Hard on 14/07/2021. +// + +import Foundation +import AppKit + +// 实践发现NSStatusItem.autosaveName 在设置 isVisible=false 或 true后,并不能恢复到原来的位置,同下面这个issue +// https://github.com/feedback-assistant/reports/issues/200 +// 也是同样使用了这个issue中 @curthard89 的方法来解决这个问题 +class StatusBarController: NSObject { + static var system = StatusBarController() + + lazy private(set) var items = Set() + private let defaults = UserDefaults.standard + + deinit { + for item in items { + removeObserver(autosaveName: item.autosaveName) + } + } + + func removeStatusItem(_ item: NSStatusItem) { + items.remove(item) + } + + func statusItem(autosaveName: NSStatusItem.AutosaveName, + width: CGFloat) -> NSStatusItem { + // it is important we load the default and then add an observer + // before we ask the os for the item as the item will instantly + // remove the user preference + addObserver(autosaveName: autosaveName) + let item = NSStatusBar.system.statusItem(withLength: width) + items.insert(item) + + // this is the line that will cause the bug + item.autosaveName = autosaveName + return item + } + + + fileprivate func defaultsKey(_ autosaveName: NSStatusItem.AutosaveName) -> String { + return "NSStatusItem Preferred Position \(autosaveName)" + } + + fileprivate func addObserver(autosaveName string: NSStatusItem.AutosaveName) { + let options: NSKeyValueObservingOptions = [.new, .old] + defaults.addObserver(self, forKeyPath: defaultsKey(string), + options: options, + context: nil) + } + + fileprivate func removeObserver(autosaveName: NSStatusItem.AutosaveName) { + defaults.removeObserver(self, forKeyPath: defaultsKey(autosaveName)) + } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, + change: [NSKeyValueChangeKey : Any]?, + context: UnsafeMutableRawPointer?) { + // settings .autosaveName on the item after it has been created will + // cause null to be set for the position, this will simply write back + // the old value to the defaults + if let dict = change, dict[.newKey] is NSNull, let oldPosition = dict[.oldKey] { + defaults.set(oldPosition, forKey: keyPath!) + } + } + +}