From fa5a345b040365e7cd0a20094bfbf96722d730d1 Mon Sep 17 00:00:00 2001 From: shuntagami Date: Sun, 22 Mar 2026 17:00:00 +0900 Subject: [PATCH 1/4] Add opt-in override for standard volume media keys. Keep the current safety behavior by default, but allow advanced users to force-capture standard volume media keys even when macOS output volume is controllable. Made-with: Cursor --- MonitorControl/Enums/PrefKey.swift | 3 +++ MonitorControl/Support/MediaKeyTapManager.swift | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MonitorControl/Enums/PrefKey.swift b/MonitorControl/Enums/PrefKey.swift index 76b5f29..39dbdf7 100644 --- a/MonitorControl/Enums/PrefKey.swift +++ b/MonitorControl/Enums/PrefKey.swift @@ -78,6 +78,9 @@ enum PrefKey: String { // Use fine OSD scale for volume case useFineScaleVolume + // Always capture standard volume media keys even when macOS output volume is controllable + case forceStandardVolumeMediaKeys + // Use smoothBrightness case disableSmoothBrightness diff --git a/MonitorControl/Support/MediaKeyTapManager.swift b/MonitorControl/Support/MediaKeyTapManager.swift index f484a6e..df68108 100644 --- a/MonitorControl/Support/MediaKeyTapManager.swift +++ b/MonitorControl/Support/MediaKeyTapManager.swift @@ -166,8 +166,8 @@ class MediaKeyTapManager: MediaKeyTapDelegate { let keysToDelete: [MediaKey] = [.brightnessUp, .brightnessDown] keys.removeAll { keysToDelete.contains($0) } } - // Remove volume related keys if audio device is controllable - if let defaultAudioDevice = app.coreAudio.defaultOutputDevice { + // Remove volume related keys if audio device is controllable unless the user opted into force-capturing them. + if !prefs.bool(forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue), let defaultAudioDevice = app.coreAudio.defaultOutputDevice { let keysToDelete: [MediaKey] = [.volumeUp, .volumeDown, .mute] if prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue) == MultiKeyboardVolume.audioDeviceNameMatching.rawValue { if DisplayManager.shared.updateAudioControlTargetDisplays(deviceName: defaultAudioDevice.name) == 0 { From 7081f54e3e66677a3523e303cfb5b0016e6ada22 Mon Sep 17 00:00:00 2001 From: shuntagami Date: Sun, 22 Mar 2026 17:32:24 +0900 Subject: [PATCH 2/4] Add Keyboard preference toggle for forced volume key capture. Expose an explicit UI switch for force-capturing standard volume keys so advanced users can opt in without using hidden defaults commands. Made-with: Cursor --- MonitorControl/UI/Base.lproj/Main.storyboard | 15 +++++++++++++++ MonitorControl/UI/en.lproj/Main.strings | 3 +++ .../Preferences/KeyboardPrefsViewController.swift | 15 +++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/MonitorControl/UI/Base.lproj/Main.storyboard b/MonitorControl/UI/Base.lproj/Main.storyboard index f5a9bb4..15a3e89 100644 --- a/MonitorControl/UI/Base.lproj/Main.storyboard +++ b/MonitorControl/UI/Base.lproj/Main.storyboard @@ -731,6 +731,7 @@ + @@ -1138,6 +1139,19 @@ + + + + @@ -1180,6 +1194,7 @@ + diff --git a/MonitorControl/UI/en.lproj/Main.strings b/MonitorControl/UI/en.lproj/Main.strings index 7c40246..01d83d5 100644 --- a/MonitorControl/UI/en.lproj/Main.strings +++ b/MonitorControl/UI/en.lproj/Main.strings @@ -415,5 +415,8 @@ /* Class = "NSButtonCell"; title = "Show percentages"; ObjectID = "ZUu-MR-XwA"; */ "ZUu-MR-XwA.title" = "Show percentages"; +/* Class = "NSButtonCell"; title = "Force capture standard volume and mute keys"; ObjectID = "5V3-gQ-jWm"; */ +"5V3-gQ-jWm.title" = "Force capture standard volume and mute keys"; + /* Class = "NSTextFieldCell"; title = "Combined dimming switchover point:"; ObjectID = "zv8-pZ-OPy"; */ "zv8-pZ-OPy.title" = "Combined dimming switchover point:"; diff --git a/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift b/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift index 8bccf3a..0492461 100644 --- a/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift +++ b/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift @@ -33,6 +33,7 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { @IBOutlet var multiKeyboardVolume: NSPopUpButton! @IBOutlet var useFineScale: NSButton! @IBOutlet var useFineScaleVolume: NSButton! + @IBOutlet var forceStandardVolumeMediaKeys: NSButton! @IBOutlet var separateCombinedScale: NSButton! @IBOutlet var rowKeyboardBrightnessPopUp: NSGridRow! @@ -92,9 +93,11 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { if self.keyboardVolume.selectedTag() == KeyboardVolume.disabled.rawValue { self.multiKeyboardVolume.isEnabled = false self.useFineScaleVolume.isEnabled = false + self.forceStandardVolumeMediaKeys.isEnabled = false } else { self.multiKeyboardVolume.isEnabled = true self.useFineScaleVolume.isEnabled = true + self.forceStandardVolumeMediaKeys.isEnabled = true } if self.multiKeyboardBrightness.selectedTag() == MultiKeyboardBrightness.focusInsteadOfMouse.rawValue { @@ -152,6 +155,7 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { self.multiKeyboardVolume.selectItem(withTag: prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue)) self.useFineScale.state = prefs.bool(forKey: PrefKey.useFineScaleBrightness.rawValue) ? .on : .off self.useFineScaleVolume.state = prefs.bool(forKey: PrefKey.useFineScaleVolume.rawValue) ? .on : .off + self.forceStandardVolumeMediaKeys.state = prefs.bool(forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) ? .on : .off self.separateCombinedScale.state = prefs.bool(forKey: PrefKey.separateCombinedScale.rawValue) ? .on : .off self.updateGridLayout() } @@ -189,6 +193,17 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { } } + @IBAction func forceStandardVolumeMediaKeysClicked(_ sender: NSButton) { + switch sender.state { + case .on: + prefs.set(true, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) + case .off: + prefs.set(false, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) + default: break + } + app.updateMediaKeyTap() + } + @IBAction func separateCombinedScale(_ sender: NSButton) { switch sender.state { case .on: From f41b3b966a3497a6bd31c6686afcbe49d50fa8cb Mon Sep 17 00:00:00 2001 From: shuntagami Date: Sun, 22 Mar 2026 17:43:25 +0900 Subject: [PATCH 3/4] Adjust keyboard settings layout for forced volume key capture. Keep the new volume-key override toggle visible in Keyboard settings while preserving the opt-in behavior for advanced users. Made-with: Cursor --- MonitorControl/UI/Base.lproj/Main.storyboard | 14 +------------- .../Preferences/KeyboardPrefsViewController.swift | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/MonitorControl/UI/Base.lproj/Main.storyboard b/MonitorControl/UI/Base.lproj/Main.storyboard index 15a3e89..6d215ca 100644 --- a/MonitorControl/UI/Base.lproj/Main.storyboard +++ b/MonitorControl/UI/Base.lproj/Main.storyboard @@ -731,7 +731,6 @@ - @@ -1130,19 +1129,8 @@ - - - - - - - - - - - + + + + + + + + @@ -1182,7 +1181,6 @@ - diff --git a/MonitorControl/UI/en.lproj/Main.strings b/MonitorControl/UI/en.lproj/Main.strings index 01d83d5..41aa602 100644 --- a/MonitorControl/UI/en.lproj/Main.strings +++ b/MonitorControl/UI/en.lproj/Main.strings @@ -415,8 +415,8 @@ /* Class = "NSButtonCell"; title = "Show percentages"; ObjectID = "ZUu-MR-XwA"; */ "ZUu-MR-XwA.title" = "Show percentages"; -/* Class = "NSButtonCell"; title = "Force capture standard volume and mute keys"; ObjectID = "5V3-gQ-jWm"; */ -"5V3-gQ-jWm.title" = "Force capture standard volume and mute keys"; +/* Class = "NSMenuItem"; title = "Standard keys (force capture)"; ObjectID = "fVk-mR-9Xp"; */ +"fVk-mR-9Xp.title" = "Standard keys (force capture)"; /* Class = "NSTextFieldCell"; title = "Combined dimming switchover point:"; ObjectID = "zv8-pZ-OPy"; */ "zv8-pZ-OPy.title" = "Combined dimming switchover point:"; diff --git a/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift b/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift index 8124e2a..8bccf3a 100644 --- a/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift +++ b/MonitorControl/View Controllers/Preferences/KeyboardPrefsViewController.swift @@ -33,7 +33,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { @IBOutlet var multiKeyboardVolume: NSPopUpButton! @IBOutlet var useFineScale: NSButton! @IBOutlet var useFineScaleVolume: NSButton! - @IBOutlet var forceStandardVolumeMediaKeys: NSButton! @IBOutlet var separateCombinedScale: NSButton! @IBOutlet var rowKeyboardBrightnessPopUp: NSGridRow! @@ -93,11 +92,9 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { if self.keyboardVolume.selectedTag() == KeyboardVolume.disabled.rawValue { self.multiKeyboardVolume.isEnabled = false self.useFineScaleVolume.isEnabled = false - self.forceStandardVolumeMediaKeys.isEnabled = false } else { self.multiKeyboardVolume.isEnabled = true self.useFineScaleVolume.isEnabled = true - self.forceStandardVolumeMediaKeys.isEnabled = true } if self.multiKeyboardBrightness.selectedTag() == MultiKeyboardBrightness.focusInsteadOfMouse.rawValue { @@ -112,7 +109,7 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { self.rowUseAudioNameText.isHidden = false self.rowUseAudioMouseText.isHidden = true } else { - self.rowUseAudioNameText.isHidden = false + self.rowUseAudioNameText.isHidden = true self.rowUseAudioMouseText.isHidden = false } } @@ -155,7 +152,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { self.multiKeyboardVolume.selectItem(withTag: prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue)) self.useFineScale.state = prefs.bool(forKey: PrefKey.useFineScaleBrightness.rawValue) ? .on : .off self.useFineScaleVolume.state = prefs.bool(forKey: PrefKey.useFineScaleVolume.rawValue) ? .on : .off - self.forceStandardVolumeMediaKeys.state = prefs.bool(forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) ? .on : .off self.separateCombinedScale.state = prefs.bool(forKey: PrefKey.separateCombinedScale.rawValue) ? .on : .off self.updateGridLayout() } @@ -193,17 +189,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane { } } - @IBAction func forceStandardVolumeMediaKeysClicked(_ sender: NSButton) { - switch sender.state { - case .on: - prefs.set(true, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) - case .off: - prefs.set(false, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) - default: break - } - app.updateMediaKeyTap() - } - @IBAction func separateCombinedScale(_ sender: NSButton) { switch sender.state { case .on: