diff --git a/MonitorControl/Support/AppDelegate.swift b/MonitorControl/Support/AppDelegate.swift index 297e0dd..6d1013b 100644 --- a/MonitorControl/Support/AppDelegate.swift +++ b/MonitorControl/Support/AppDelegate.swift @@ -11,11 +11,17 @@ import SimplyCoreAudio import Sparkle class AppDelegate: NSObject, NSApplicationDelegate { - let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + let statusItem: NSStatusItem = { + let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + item.behavior = .removalAllowed + return item + }() var mediaKeyTap = MediaKeyTapManager() var keyboardShortcuts = KeyboardShortcutsManager() let coreAudio = SimplyCoreAudio() var accessibilityObserver: NSObjectProtocol! + var statusItemObserver: NSObjectProtocol! + var statusItemVisibilityChangedByUser = true var reconfigureID: Int = 0 // dispatched reconfigure command ID var sleepID: Int = 0 // sleep event ID var safeMode = false @@ -83,7 +89,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationWillTerminate(_: Notification) { os_log("Goodbye!", type: .info) DisplayManager.shared.resetSwBrightnessForAllDisplays(noPrefSave: true) - self.statusItem.isVisible = true + self.updateStatusItemVisibility(true) } private func setPrefsBuildNumber() { @@ -169,6 +175,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.sleepNotification), name: NSWorkspace.willSleepNotification, object: nil) NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotification), name: NSWorkspace.didWakeNotification, object: nil) _ = DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name(rawValue: NSNotification.Name.accessibilityApi.rawValue), object: nil, queue: nil) { _ in DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.updateMediaKeyTap() } } // listen for accessibility status changes + self.statusItemObserver = statusItem.observe(\.isVisible, options: [.old, .new]) { _, _ in self.statusItemVisibilityChanged() } } @objc private func sleepNotification() { @@ -270,7 +277,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { if let bundleID = Bundle.main.bundleIdentifier { prefs.removePersistentDomain(forName: bundleID) } - app.statusItem.isVisible = true + app.updateStatusItemVisibility(true) self.setDefaultPrefs() self.checkPermissions() self.updateMediaKeyTap() @@ -352,4 +359,16 @@ class AppDelegate: NSObject, NSApplicationDelegate { onboardingVc?.window?.center() NSApp.activate(ignoringOtherApps: true) } + + private func statusItemVisibilityChanged() { + if !self.statusItem.isVisible, self.statusItemVisibilityChangedByUser { + prefs.set(MenuIcon.hide.rawValue, forKey: PrefKey.menuIcon.rawValue) + } + } + + func updateStatusItemVisibility(_ visible: Bool) { + statusItemVisibilityChangedByUser = false + statusItem.isVisible = visible + statusItemVisibilityChangedByUser = true + } } diff --git a/MonitorControl/Support/MenuHandler.swift b/MonitorControl/Support/MenuHandler.swift index fcd79aa..fd61cd5 100644 --- a/MonitorControl/Support/MenuHandler.swift +++ b/MonitorControl/Support/MenuHandler.swift @@ -33,7 +33,7 @@ class MenuHandler: NSMenu, NSMenuDelegate { if !dontClose { self.cancelTrackingWithoutAnimation() } - app.statusItem.isVisible = prefs.integer(forKey: PrefKey.menuIcon.rawValue) == MenuIcon.show.rawValue ? true : false + app.updateStatusItemVisibility(prefs.integer(forKey: PrefKey.menuIcon.rawValue) == MenuIcon.show.rawValue ? true : false) self.clearMenu() let currentDisplay = DisplayManager.shared.getCurrentDisplay() var displays: [Display] = [] @@ -185,7 +185,7 @@ class MenuHandler: NSMenu, NSMenuDelegate { self.addDisplayMenuBlock(addedSliderHandlers: addedSliderHandlers, blockName: display.readPrefAsString(key: .friendlyName) != "" ? display.readPrefAsString(key: .friendlyName) : display.name, monitorSubMenu: monitorSubMenu, numOfDisplays: numOfDisplays, asSubMenu: asSubMenu) } if addedSliderHandlers.count > 0, prefs.integer(forKey: PrefKey.menuIcon.rawValue) == MenuIcon.sliderOnly.rawValue { - app.statusItem.isVisible = true + app.updateStatusItemVisibility(true) } } diff --git a/MonitorControl/View Controllers/Preferences/MenuslidersPrefsViewController.swift b/MonitorControl/View Controllers/Preferences/MenuslidersPrefsViewController.swift index a27237c..3d132ea 100644 --- a/MonitorControl/View Controllers/Preferences/MenuslidersPrefsViewController.swift +++ b/MonitorControl/View Controllers/Preferences/MenuslidersPrefsViewController.swift @@ -80,6 +80,7 @@ class MenuslidersPrefsViewController: NSViewController, SettingsPane { override func viewDidLoad() { super.viewDidLoad() self.populateSettings() + prefs.addObserver(self, forKeyPath: PrefKey.menuIcon.rawValue, context: nil) } func populateSettings() { @@ -210,4 +211,12 @@ class MenuslidersPrefsViewController: NSViewController, SettingsPane { app.updateMenusAndKeys() self.updateGridLayout() } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + guard let object = object as? AnyObject else { return } + if object === prefs, keyPath == PrefKey.menuIcon.rawValue { + self.populateSettings() + self.updateGridLayout() + } + } }